Complete ASP.NET 5 Web API Development | Trevoir Williams | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Complete ASP.NET 5 Web API Development

teacher avatar Trevoir Williams, Jamaican Software Engineer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

51 Lessons (8h 60m)
    • 1. Introduction

    • 2. Install Visual Studio 2019 Community Edition and .Net 5 SDK

    • 3. UPDATE: Install Visual Studio 2022 Community Edition and .NET 6

    • 4. Setup GitHub Account

    • 5. Install and Explore PostMan

    • 6. Create and Tour Web API Project

    • 7. UPDATE - Upgrade to .NET 6

    • 8. Configure Logging using SeriLog

    • 9. Explore Swagger UI

    • 10. CORS Configuration

    • 11. Review and Add Changes to GitHub

    • 12. Implement Data Classes and Entity Framework

    • 13. Seed Data In Tables

    • 14. Setup Service Repositories and Dependency Injection

    • 15. UPDATE - Strongly Type Includes for Unit Of Work

    • 16. Setup AutoMapper and DTOs

    • 17. Review and Add Changes to GitHub

    • 18. Overview - Setting Up GET Endpoints

    • 19. Construct GET Endpoint

    • 20. Construct GET By Id Endpoint

    • 21. Setup GET Endpoints For Hotels

    • 22. Final Touches and Add Changes to GitHub

    • 23. Securing Your API - Section Overview

    • 24. Setup User Identity Core

    • 25. User Registration Endpoint

    • 26. IMPORTANT - User Registration Endpoint Fix

    • 27. Add User Roles

    • 28. Explore JSON Web Tokens (JWT)

    • 29. Implement JWT Authentication

    • 30. Protecting Endpoints

    • 31. Review and Add Changes to GitHub

    • 32. Construct POST Endpoint

    • 33. Construct PUT Endpoint

    • 34. Construct DELETE Endpoint

    • 35. Review and Add Changes to GitHub

    • 36. Value Added Functions - Section Overview

    • 37. Implement Paging

    • 38. Global Error Handling

    • 39. Implementing API Versioning

    • 40. Implementing Caching

    • 41. Rate Limiting and Throttling

    • 42. Review and Add Changes to GitHub

    • 43. Architecture Changes - Section Overview

    • 44. Setup Data Models Project

    • 45. Setup Application Core Project

    • 46. Clean up and Test

    • 47. Review Modifications and Benefits

    • 48. Configure Hosting Environment - IIS and SQL Server

    • 49. Publish Application to IIS and SQL Server

    • 50. Create Microsoft Azure Account

    • 51. Deploy Application and Database to Microsoft Azure

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class


Learn how to build a RESTful API using ASP.Net Core API, Entity Framework, enterprise grade practices for a scalable and future proofed Web API solution. We will implement various support tools for logging, documentation, security and error handling.

ASP.NET Core based on the new .NET 5 runtime, is Microsoft's modern, cross-platform framework for building enterprise ready web applications. In this course, you will learn everything you need to know about building a RESTful API using .NET 5, from understanding the folder structure and files, to building and deploying a complete web API.

Why Learn ASP.NET Core / .NET 5

Microsoft .NET is the platform that drives the business technology of many of the top corporations in the United States and many other countries. It is the predominant technology used to drive enterprise-scale business technology. Companies have chosen .NET because for its proven scalability, reliability, and support.

The .NET language of choice to learn is C#, as it is among the most widely used languages today. It’s a general purpose programming language that can handle almost any problem, from desktop to mobile to dynamic web applications. As such, there is a high demand across the world for .NET developers in a variety of industries, so that means that more jobs are available for candidates with a foundation built upon .NET technologies.

Why Learn to Build An API

The acronym API means Application Programming Interface. The ability to design and maintain an API is an important toolset for the modern web developer. It allows you to extend the accessibility of your software to external applications and other developers, leading to a more global software solution.

Build A Strong Foundation in .NET Core / .NET 5 Programming:

  • Build a fully data driven REST Web API using cutting edge technology

  • Create a database using Entity Framework Core

  • Unit Of Work and Generic Repository Pattern

  • Dependency Injection

  • Setup Logging using SeriLog

  • Setup API documentation using SwaggerUI

  • Understand the REST design principles

  • Understand C# 9 and .Net Core Web Syntax

  • Understand user Authentication using JWT (JSON Web Tokens)

  • Understand how to use Data Transfer Objects (DTOs) and AutoMapper

  • Manage Packages with NuGet Manager

  • Understand .NET 5 workflows, tools and application development

  • Setup GitHub for Source Control

  • Deploy Applications and Database to Microsoft Azure

Content and Overview

To take this course, you will need to have some knowledge of Object Oriented Programming, if not C#. Even if you do not have much exposure to the .NET development stack, this course is very beginner friendly and chock full of development tips.

This is a huge course. Over 8 hours of premium content, but smartly broken up to highlight a set of related activities based on each module in the application that is being built. We will also look at troubleshooting and debugging errors as we go along; implementing best practices; writing efficient logic and understanding why developers do things the way they do. Your knowledge will grow, step by step, throughout the course and you will be challenged to be the best you can be.

We don't do things the perfect way the first time; that is not the reality of writing code. We make mistakes and point them out and fix them around them. By doing this, we develop proficiency in using debugging tools and techniques. By the time you have finished the course you will have moved around in Visual Studio and examined logic and syntax errors so much, that it will be second nature for you when working in the .NET environment. This will put your new learned skills into practical use and impress your boss and coworkers.

Meet Your Teacher

Teacher Profile Image

Trevoir Williams

Jamaican Software Engineer


Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Introduction: Hey guys, I wanted to take this time to welcome you to this new course, ultimate five web API Development Guide. Now, it's type is a multiple bots. I can assure you the content shorter lives up to the building. In this course, you'll learn how to create a maintainable Web API using five, which is the latest and greatest and Microsoft and development stuck Entity Framework. And we will explore many enterprise level design patterns on considerations when it comes to designing and API. I am your instructor for this course. My name is true. Who are Williams? I'm a software engineer and part-time lecturers. Let's explore what an API is, the letters AP and the IR, short for Application Programming Interface. Pretty much an API is a software interface that acts as an intermediary between two applications. So let's say you can access Facebook like functionalities from an app that is not a Facebook app. So this has the top to Facebook and allow you to do facebook live things. Well, that is communicating with Facebook through an API. So in this course, we will learn how to build that kind of interface to allow persons to access an underlying data store that we will be building. Using functionality that we will be building are using clients that they will need to build, whether it's for a mobile or web or any other type of device. So APIs or at least the type of API that we will be building are based on the rest principles. So we will learn wrist and arrested short for representational state transfer. It is a very popular Web API standard and it is used across many platforms. So though we will be building the API core, the API can be consumed by clients from many other development stacks. In addition to this, we will be learning how to use Dominic core five, we'll be looking at to understand the services and oh, the whole application flow works. And we'll also be looking at using enterprise level hotter. So best practices that we can put into the code such that when we are ready to expand, whether through our own self-discovery or in an enterprise setting. We won't have to pull up too much of our application to do that. Well, we can just tap on components as we go along. So in a nutshell, you're going to learn five and Entity Framework forward wind to be using quote firstly, it's amazing development and exploring. Once again, key encoding patterns will be looking at API authentication using JSON web tokens are JWT for short haul, we can protect them higher than our endpoints and protect them from unauthorized or unwanted access. We'll look at understanding the Dark Net core service pipeline and all we can extend them and puts in our own middleware, have looking at API testing and logging sober using Postman and serial out for our API testing and logging purposes respectfully, and we'll also be looking at whole swagger can play a part in documenting our API and also helping with artistic source control. We will be using GitHub so that we can securely store or code and be able to roll back should we need to. And then we look at, after building on all of these wonderful things, how exactly we allow our API to be accessed, whether in a company setting or by the World. Now, this course has quiet somebody tenets. It's about ten hours long and you will be learning a lot of things. So bulkload, get ready for this journey and I'm very excited to have you along. 2. Install Visual Studio 2019 Community Edition and .Net 5 SDK: Hey guys, today we're going to get started with installing Visual Studio Community Edition five. Now our journey begins here on the Visual Studio website, which you can get to through a simple Google search. Or you can try to reproduce this URL, which is Visual Studio dot slash VS slash community. Now there are different additions of Visual Studio. And community is the one that's, it's free for individual use and that's the one that we will use. So you can go ahead and download Visual Studio, which will give you the Visual Studio Installer. And once that is completed, we can go ahead and run that file. We'll throw in the security checkpoints that you might have, but you may proceed to allow the installer to begin. And all this is where you actually define what Visual Studio will be capable of. So these are called workloads, and each workload will expose a different feature set to you. So for web development, you'll want to get the and web development workload. For desktop development. You want to get the net desktop development or upload. And for any other SDK or type of project that you may want to develop, you can go ahead and get the workload associated with it. No, for this exercise, we want to prepare our results studio with the necessary resources for web development. Once again, you can go ahead and take as many of these workloads. Each one will come with its own size and it tells you how much space is required based on the ones that you select. But at minimum for web development, you want to make sure you have and web development ticked. You can go ahead and take the other development tools if you wish. But I'm not willing to do that because these are framework 644.84.6, sorry, 4.74.8. But we are going to be installing document five in a few minutes so you can go ahead and do this and let Visual Studio install. This will take a while so you can grab a cup of coffee and come back. Now once that download and installation is completed, you have two options. You can go ahead and sign in. And sign meaning you sign in with your live cones. If you have one, if not, then you go ahead and create one. It's free and it makes life easier if you just create one and actually sign in. But I'll just go ahead with a not null maybe later option. And then you choose your general settings. So I light the dark theme and you can choose what they want, what development settings or general. I'll just leave mine on general, even though we're doing what development. But they basically just optimize certain keyboard shortcuts and the layout based on your selection. I'll leave mine on general. I'll start with Visual Studio. Alright, so once that is done, you are going to be prompted with this snow. If you don't get this, then that's fine. But here's why I would've suggested that you sign in with their life cones because then all you have a 30 day trial period. And if you don't want top of the cone, then they'll basically just tell you to exit. So you can actually just go ahead and sign in. So I'm just going to sign in with my own. And once you have signed it and then you'll see that it is not licensed to you and it just looks submit more inviting. So now instead of exiting Visual Studio, I can close. And this is Visual Studio at the very basic level. Now we have Visual Studio. What we also need five. So you can get to the net five download page through a simple Google search once again. Or you try to reproduce this URL, whichever one you find easier to do. At this point, you want to download the SDK and the runtime. So let me start by closing Visual Studio because it needs to install extensions for it. And installer is always available for you. So if you fail to add a workload, just so you know, you can actually just click modify and then it will relaunch that pH with all the worker would say if later on you want it to do something new, you just need to modify that work load and then you'll get those Project Templates accordingly. I'm going to close Visual Studio, however, so we can continue with our installations. So we'll get five. Now you can see that the SDKs available based on your OS, I have a Windows 64 bits OS working with retinal, so I'll go ahead and download that. And while that one is downloading and just Lindsay hit the Back button and go over to the runtime, which is absolutely necessary for hosting. So you see it's the run-time support. So if you're going to be hosting five application on, on a local server, then you definitely need the runtime. So you can just get this hosting bundle that they have there available for download. So you can just download both and when they're both finished. So when the SDKs finished, you can go ahead and install that 1 first. It shouldn't take too long. And okay, so it's successful. After we've installed the SDK, then we want to just make sure that we have there own time. Also agree to anything, and go ahead and run your installation. And it will let you know when it is successfully completed, know that we have the SDK is completely installed. I just wanted to launch Visual Studio and show you what you get with those SDKs. So if I go ahead and create a brand new project because of the workloads that I have available to me, I will see different project templates. So I only chose the web worker node. So I have the ability to do a regular console up. I have the core. As a matter of fact, I think that this one comes because of the desktop workload, but at this point I'm not trying to figure out which worked, who would belongs to which. Just know that if you are going to be doing our web project, you have the option to choose a core web application, a blazer application, and you can choose them whether you will not make for framework, someone to choose a.NET Core Web application. This is not the actual application that we're building. I'm just showing you your options. So then we go ahead and put the project name could create. Then from the drop-down list here, you can choose whether you want a Core 2.13.1 or the latest dominate core 5. And with that, you will be able to choose the different templates and proceed. So when we come back, we'll actually create a project and do a tour off the folder structures. 3. UPDATE: Install Visual Studio 2022 Community Edition and .NET 6: Hey guys. In this lesson we'll be installing Visual Studio 2022, which ships with dotnet six, which is the fastest dotnet yet. So to get started, we just need to go over to Visual Studio dot slash downloads. And then we will go ahead and hit the free download on the community edition, which will then give us an installer. So once we run that installer, we will be able to select the workloads that we want. Workloads really refer to the libraries or to supporting libraries for the type of up that you're interested in creating. So in this case, we definitely want to get that web development on web development workload. But then if you are interested in other technologies, you can go ahead and select them. So you can see I have several workloads selected with Azure development, NodeJS and desktop development. So you can go ahead and split those also. I think that they will come in handy with other projects that you might end up building all in all, once you have done that, you can go ahead and hit Install, which would be done by the bottom right-hand corner. Of course, the more workloads you select is the bigger the download size. So once you've completed that, then you can continue. Now when that download is finished, you may get certain options that I am not going to get because I already have it installed. So this will walk you through what do I expect? You may get an option where you get to choose your theme. As you can see, I'm using the dark theme, but then you do have the option of a light theme, a blue theme. And the thing is that Visual Studio 22 has many more themes than its predecessors. So even if you don't want light the initial themes, you can get all the themes if you need them. Also, you may be prompted to sign in. So if you already have 2019 installed on your machine and you are just installed in 2022, you already signed into 2019, then it probably won't prompt you to sign in again. However, if this is your first installation of Visual Studio, you may be prompted to sign in or creates a live account, which point you would want to just use your Microsoft issued at live at all loci are taught me a lot com cones, or you can just go ahead and create one. And if I if my memory serves me correct, you can use an another non-Microsoft email address, secretes saliva, cold. 4. Setup GitHub Account: Hey guys, in this video we'll be creating or GitHub accounts. And this is a really simple stuff, gets old, makes it very easy for us to sign up. You just need to go to Does GIT HUB DOT COM,, and you will land on this page. Now from here, if you already have an account and you can sign in and you can pretty much stop watching the video here. If you don't. However, then the center form is right here. You can do a little reading, just gets an appreciation of what GitHub is four and it's all about, they do have pricing, so they do offer enterprise plans and education plans and different plants or different situations. But for the solar developer or for very small teams that may not be enterprise-level than they do. Give you a lot for free. So to sign up, you need only put in a user name and email address and a password. And once you have provided all those things and provided that your username is unique enough, of course, then you click sign up for GitHub and you should be in. So I already have an account, so I'm really just going to sign in. You saw my eyebrows are going crazy trying to provide information. So I'm just going to sign in with my existing account. So that's my well, you can use your username or email addresses to sign in and the password. And here I am, this is my landing page, so they actually give you a sense of community. It's almost like a Facebook for developers to some extent, you can follow people. And once they're following people, you see their activities on the landing page, you can jump to your repository. So obviously if you're new to gets up, then you wouldn't have anything listed to the side here. What I am not new. I've been quite busy putting content on YouTube, almost any little pet project that's I start, I have a GitHub repository or actually I need to go through it. So and also I've had students add me to their repose in the past so that we could collaborate. Maybe they were having a problem and I could just verify their code through the repository. All of those things are possible through this verbal photo. But once you have created your cones and you're signed in and well, you obviously wouldn't see what's I'm seeing once again. But then that would complete the sign-up. 5. Install and Explore PostMan: Hey guys, in this video we're going to be installing postman or porcelain is an excellent tool for collaboration and APA testing and validation on all of those wonderful things. So it's pretty easy to install really. You just go to pause Postman does light Luca who delivers your mail, You don't know the up. And of course you choose your oil. So 64-bit Windows, and then the download starts. Alright, so once that download is finished, you can go ahead and open the installation file, run the installer. All right, so when it is finished, you will either see a screen prompting you to sign up or sign in, or you'll see this screen either way, if you see something to sign in, I would encourage you to do so. Actually had it's on my machine already. So the flow may not be exactly like this. But if you do see this page come up, then it's fine. You can just click the X and you can take it off. And I'm not signed in anyway. So if you do see the offscreen looking something like this, then you can just go ahead and create an cones soluble. They can create an OK cones quite easily username, password, or you just sign in with Google. I like to just sign in with Google. And the thing is that parser will keep a history of every test that you've gone to once you will have on up cones. Alright, so I'm just going to go ahead and sign in with Google. Or it's on. Once you're signed in, then you know you can start working. So I'm just going to show you guys a sample of what Postman is capable off. Firstly, I'm going to suggest it's a dark mode because the mode is cool. And then I'm going to create a new request windows. So using this plus sign, just like any browser with the plus signs at the top you can see a plus sign, and that gives you a new request. Now I already went ahead and search for some public APIs, as we discussed, APIs base gotta earn our gateway into your database. So people have APIs, various people have APIs. And I found this website any dash And just triangle back to the very first bit so you can see what they have to offer. So from the landing page, peers issue you a bunch of public facing APIs. So you go, you can just go ahead and click one and, you know, test it out. So I went over to the Oxford dictionary one where I would get a list of languages. So they show you all of the endpoints, right? So in building all the API, they link to the database shore dab, a common URL, but then they have different endpoints that will give different bits of information. And then they have different methods, GET and post and put any off some other ones. But the fact is that you have to know the request type. You have to know the URL through which you can get that request satisfied. You have to know if you have to pass in headers. So here I know I need applications. And ID. And then they show me the responses. So 200 means o, t, and initial men example in JSON what that response would be. And then 404 means not found. 500 means there's an internal error usually with the home server, not with you, right? So for for Musa, you're probably searching for something that doesn't exist. 500 means that the API provider has an error. Alright, so I switched from any API and wanted to free, for free forex api dot cottons, sorry, so I took a closer look at any API URL as all of those API is required, that you would have hot air no cones B, our registered user probably being user off those platforms you can look through, you see Instagram is a YouTube, Google. Most of those are predicted API, so they're using so mom auto security or owned it. And we're going to go through all of those techniques in this course. But right now I just want to start with a quick win and satisfaction of seeing what postman can do and the relevance of it, right? So I phoned free forex, right again to stop that's in free for And then we'll go with the documentation so that landing page is actually their demo of them consuming the data through the API that they're exposing, right? So they have a database builtin API. And then the, they're making a series of API calls to show the trading index between euro, USD you are and GBP, etcetera, etcetera. So if I go to documentation, they will give me the Terms of Use, tell me how to use it. So documentation is very, very important and vital when it comes to the APIs, I will be using swagger sorter UI to our swash vocal. When we get there, you'll see, but we'll be focusing on documenting our APIs to a great extent also. So from here they show you that you have the, that's the domain that the API is hosted on, right? And then as you scroll down, you'll see the different types of functionality that they exposed. So that is a good grades beta, right? And then they say to me the request, it is a GET request. And then you have the, the, the endpoints, sorry, the URL and the endpoint, that's what it needs to look like. And this is a sampler response. All right, and if you look through, you see another one. You can get different peers. So right here you're going to look, he'll be euro-USD E1 and the return that the results of that query for you. And then in this one, you can get more than one if you want. So you just put in both indexes that you're interested in as the parameter in that endpoint. Alright, so that's a query string for the values the queries are on. And then this is the response from the API. Once that queries are an NDA data is phoned. No, the arrow chords tell a good story because then you pass into periods that don't exist in their system than they're telling you that if you don't pass in any setting is required and if you pass in something that's not there, then you will see an error code 102. So you have standard error codes and you have some miracles. You yourself can make. Let's try this sample. So I'm going to try the first one where I'm getting euro and USD. So I'm just going to copy this link, which they said, that's all you get to the data on this end point. And then I'm going to open up Postman. And then what I'm going to do is pierced it inside of this set says enter request URL, that's what we just copied, right? Request. And the URL, I paste the request URL. And then the verb here, LC can do GET, post, PUT, patch, delete, you have a bunch of them. So get is usually used when you are expecting to retrieve data, right? So get and then free for its API. Well, whatever the request URL was, No, it's committed to memory because it's there in the documentation. And then I will click send, know what postman does is mimic a call. Well, not really mimic it actually performs the call to that API endpoint and then retrieves the data in the response. So we see here, it may not be as well formatted as how it is in the documentation. Of course, they are putting their best foot forward. What does the same bit of information where getting a read and we're getting a timestamp and or getting up code of 200. If you look to the right, you will see the Status 200. Okay? So 200 is the universe of response for all k. Once you get a 200 response, you know everything is okay. So the different numbers have different meanings of words, right? The time it took to me the cost. So this is a quick API took only that's what, 2.5th and the size of the response, right? So you can always formatted. So this you can click pretty, or you can say raw or preview or visualize. I'm not sure why I pretty, Oh, that's right after change the format. So it's pretty HTML. So this is all good. And looking at this, I can say something like XML and it's not XML. I said HTML. Let me click JSON, which it is, and there we go. So now it's pretty JSON. So now it looks a bit more radical, which is being previewed in their documentation, right? So Postman is very handy when you just want to test what the response will look like. Json is the most widely-used response that I'm seeing that loosely, I like to use JSON responses. What the Clausius alternative to that would be XML. And once the data is being returned that the user expects and you've document what they can expect, then you are, you can feel confident that anybody can use APA when needed. So Postman is going to come in handy as we go boats developing our APN, Just want to validate that the responses look the way we expect them to. 6. Create and Tour Web API Project: Hey guys, welcome back. So the first thing that we need to do having So two-part environment and everything is to create our projects. So what we're going to do is launch Visual Studio. And then we're going to go to create new project. Now from here you can choose the template that you want if you have core web application at the top, go ahead and select it. If you don't, then you can just type in web in this filter and it will filter don't wear are going to be using C-Sharp. So make sure that C-sharp is selected. And while you don't have to change much else but to select the desired templates and go ahead and click Next. No, we'll be building a hotel listing API. So I'm going to call my project hotel listing. Right now that we have that we don't have to change much else. We can go ahead and click Create. If you want to select a specific location, you may go ahead and do that. Otherwise, proceed with creates. Next step has a selecting the stock that we intend to use. No, you'd have already installed five SDK and Visual Studio 2090. And so you should have gotten it or 5 As, as an option. If you don't have this, then you should have 3.1. Either way. You Candace double-back, go ahead and install the SDK. Review that video if you need to make sure you have everything installed. And then you can go ahead and select 5. And we will be building an Core Web API. Now, to the right, we have the option of adding authentication and configuring some other things. So we leave everything as is. We won't be configuring authentication here because the options that are given to us are not really what we want. So we'll be manually configuring that later on. And that would be a good exercise to help you understand how identity core gets integrated into your API. But we can leave it as no authentication, right? Null. And then we can go ahead and click Create. So now that's our project has been created. The, just the point, oh, before I move much further, the layout of my Visual Studio mean different from yours because I tend to use the Solution Explorer. On my left hand side. By default, it should be on the right, would be on the right. So that's probably what yours looks like. Either we can always dragging it and put it wherever you want. I like to have it to the left, so that's where I'll be using mine. Now the Solution Explorer is giving us a list of files and I'm just going through this in cases is your first time creating project. If it's not, then I just go over this anyway because, you know, repetition Newtons in pressure on and maybe I'll points or something that you didn't know before. But hey, so the first thing that we'll want to look at is our properties folder. So let me, let me start over. So we have what we call the solution, which is like a manifest for the list of projects that are in this solution that we're building. The project is hotel listing. I notice when I click it. It's really just an XML file with a bunch of configurations on listings and all the things needed for the project to know what its identity is. So because we 5, you see that's the target framework. If we choose, 3.1 would see something different there under properties or read them out dependencies, we see analyzers, frameworks, packages as we go along, you see this list growing, so don't get too much into what's happening there. We look at properties, we see lawn settings. So here it's like just configurations, tell the application and how it should behave when we are in debug mode. So what's very important here though, is that we did allow it to configure SSL or HTTPS when we're agreed on a project. As a result, we have this SSL port. So when we're doing our application and testing and so on will be at HTTPS colon slash slash local host colon. And then because HTTPS where using the SSL port, otherwise this would be the less secure HTTP end point. So that's just a little thing that I'm pointing all its otherwise, the other configurations we'll get into as we go along. More controllers folder, which really hoses are well controllers and these do exactly what the name suggests. They controlled application through the logic or everything goes. When we receive a request for information holy interpreted, and all of those behaviors would get defined inside of our controllers. These are the first lines of defense. Onesy heats an API endpoint, you're actually coming to a controller. And then it would say, OK, which endpoint or sit, what should I do? And then it will return accordingly. Once again, as we go on, you'll see that come to life. All right, I'm going to skip ahead to our upsetting dot JSON, which doesn't have much. We'll be modifying that. Does he go along though? But let me go on to the program.cs, which is the starting point for our applications. So here you see it runs this main functions if you ever done another language or developed in a C-sharp console applications, you notice I always start with main, at least see plus-plus C-sharp Java. All of those languages at least have a mean method, right? So once we're running our API is going to hit the mean and then main is going to basically do like a building. So what it does is it aggregates all of the middlewares on functionality and puts into the application. So it calls this method, which is really defined right below. And it does its initializations based on what is in our startup file. So if I go to startup, here's where you see where all the middlewares are added and the configurations are called at the get-go. So here we see where it wants to use controllers, add whatever libraries you need to add so that we can use our controllers. Setup swagger, solo. Traditionally swagger would have been, you'd have to implement that money early since this version API, it comes out of the box so we don't have to do too much work, but we'll be exploring what swagger is later on in case you are not quite sure what it is. We so that's configurations or configure services. Sorry, we have configure which allows us to set up some other functionality. So without getting too much into them, some of them are self-explanatory, some of them are for security reasons. As all of them are really nice, the hubs, and we are going to be adding more and more as we put more features into our API. So don't worry too much about it. The final phase in this solution would just be this model. So this model just basically represents beta or a strongly typed unit of data. And we'll be defining lots of models and data transfer objects later on. But for now, we have created our project. We should have a fair understanding of what we're looking at inside of this solution. And when we come back, we will start configuring our first app dead service in the form of logging. 7. UPDATE - Upgrade to .NET 6: Hey guys, In this lesson we're going to be looking at upgrading our project from dotnet 52, dotnet six and all this stuff is completely optional and a prerequisite for it is that you actually have installed Visual Studio 2022 already. So if you feel more comfortable just proceeding with dotnet five and Visual Studio 2019, then that is absolutely no problem. However, if you want to take that little step and go over to dotnet seeks, that's what I will guide you through doing. Ultimately though, even if you do this, upgrade, everything else in the rest of the course will fit as dotnet six is reverse compatible with everything For dotnet five. So barring these few changes, everything else should work. So the first major change that we're going to make is a target framework. So for the CSB file, this is that project file at the top here. You're going to click it and then it will become editable. So you want to change that from dotnet five to dotnet six. In addition to that change in this file, we will want to add two new library references. And those will come in the forms of Microsoft, not ASP NET cord dot JSON Patch, which will be Version 6 and Microsoft dot extension dot caching abstractions, which is also dotnet six. So if you make this adjustment, all of the packages that you will be using half to be for dotnet six. So for the duration of the course, most of it is done in dotnet five. You will see me referencing dotnet five libraries. But all you have to do is make sure that you use dotnet six instead of dotnet five. So now let's don't don't tore up settings file and this is actually optional. But they have removed the Microsoft on Microsoft dot hosting lifetime logging libraries, and they've replaced it with Microsoft dot ASP NET Core warning. So you can go ahead and meet that change. After you've done all of that, you want to just do Control Shift and B that does a build, or you can just go to build and click Build solution. And then you're probably going to see a few areas above the target, target project. So let's just jump over to the projects. Go to New get, Manage NuGet packages. If you're not very familiar with what you get, is we look at it further on in the course. But for now, the problem is that some of our libraries are still in dotnet five. So like I said, instead of referencing dotnet 5, we will reference the dotnet six version. So all you have to do is jump over to updates. Select all bucket is, do an update. Accept any problems that comes up. And then once you've done that, you can probably do a rebuild. Sometimes a builder doesn't pick up everything. So when you do a rebuild, it will clean and then restore and then build. And then we see one succeeded. So we know that our project has been updated successfully to dominate seeks. So you can go ahead and finish up the rest of this course and have fun with everything that you're going to be doing. 8. Configure Logging using SeriLog: Welcome back guys. So in this lesson we're going to be setting up our logger utilities. So our weapon of choice for this one will be serial out. That being said, there are quite a few potential tools that are out there, say UP SIR log n, log, log for net, at least those are three that I have used and I'm sure that there are others. No, I am using serial log because it is tilted as the fastest one out there. And it is very popular in the developer community. But be very objective when choosing your tool. I'm going to walk you through the configuration for Syria log and configuring the others may have some variations, but ultimately they are all geared towards doing the same thing which is logging your application activity. No, let me explain what I mean by logging application activity. There are times when unexpected events occur and if it occurs null and you hear about it five minutes later or even the instant after it happens. Sometimes it's difficult to track, especially in this context or it's an API. There's no real UI, no real feedback except on error that has occurred. So using this login utility will be able to kind of make notes as to what option triggered wat to response that would've turned out to be an error response. And even then we can see the details of set error response. So let's get started with setting up our logging. So we need to get the library's associated with serial out. So I'm just going to right-click on the project, go to manage new get packages. And then we're going to look in the boroughs section. So these are what we have installed. Your versions may be different from mine. And if you are prompted to update, be careful that you should be able to update the Microsoft on CFD enough, but just be careful when doing and needs to be ready to Roebuck in case anything Greeks. So far, no, we'll browse and we look for Syria Log dot ASP.NET Core. So you'll see this one, but that's not the one that we want. We want dots ASP.NET Core. This one has a library's dedicated to our project type. So we can go ahead and install that once again, if the version is different, it shouldn't be a major problem. And for all the problems that you're getting, just go ahead and answer in the affirmative. And then once that is done, we're just going to head over to our program.cs and begin our configuration. So all we need to do is let the application nor that where are you going to be using Siri log instead of the default logger that came with project. Because if you look in upsetting, you see that there is some semblance of a logger. They are giving you some configurations, but then this is not as robust as what we want, right? So Cirillo kind of builds on top of that and it allows us to override. So I'm going to go down to the eye holes builder. And the first thing I'm going to do is make a new line on that on their land 20 and the dots use and right, Siri log. All right. So once I do that, it's going to let me know what I need to include that library. So use your log after include that using statement. Well then that's not all. That's not something that the beginning sewn know that we have this library here. We can now go back and configure. So I'm just doing getting this cartilage of the wheel because in the bus admittedly, I've forgotten to put that in. So let us get nothing out of the way and proceed to modify our main application, which is going to initialize our logger when the application starts soap and where does winds up Putin some test log scenarios right here in the mean as our test case. So what I want to do is configure a logger object. So I'm going to say Log dot logger is equal to a new logger configuration. Alright, so what this is going to allow us to do is set some defaults and expected behaviors for our logger. So I'm just going to be breaking lined with each configuration that I add went to c dot. And the first configuration that I want is right, tool, then knots again. And then you see here they have different options. So fired on console called Alltop the box, but then they talk about sinks. So he can download specific libraries so that you can love to a database. You can log two other various files or file types based on how you need it boat, right? No, I'm only interested in file later on on this little bar database and so on. We can double-back on Add database logging tool or a suite of tools. So right, no, I just see right to file. And then this takes some parameters. So I'm going to just name the parameters them because I'm not necessarily going to tie them the specific order that they are required here in the constructors or in the overloads rather, right? So the first one that's I'm going to write is path. Path means where should this file get created? When it needs to be created or ads on path needs to be a string. So I don't want to set a set path and I'm just going to spend some time and explained here. Once again, context rules. One, you may want to have a central logging path, because once you have deployed your API on a server, you don't want to be spending on guessing where did the logo, where the log might be, you might not want it in the actual project. Right. Cause I had a log file here that's had just deleted admittedly. But you may not want it in a project because somebody de Broglie and application may not necessarily, you don't necessarily want them to go into the project files on the server to be able to access the lugs. So you can define somewhere on the network and you can define on another drive. You can just put in a path here where you know, you want your log files to goal. So I'm going to see something like C colon slash slash and when to say hotel. So I know exactly which obligation I'm dealing with when I see the folder, hotel listings, slash slash logs, right? That's my boss that I'm defining. So I'm not saying you must define the spot if it's the D drive for you. If you don't want to put in the logs, that's up to you, right. But I'm just recommending that you make it easily accessible or accessibly enough. You can find it when you need to. All right. So see hotel listings, logs, and then I'm just going to give my log file log dash dot TXT. So I'm going to explain that are seemingly random dash in a few. So that's my file path. So far, lots of arrows, but let's carry on and see what those, so I'm just breaking lines so that we can see everything. Alright. This breaking and making a sorry, indent. All right, so that's it for the path. The next configuration I'm going to put in is the output template. How do I want each line to look? Right? So I already prepared all put templates. I'm just going to paste it there and walk you through it. So once again named parameter or put templates colon and the value I want would be timestamps I'm tending it puts in a timestamp with that level of detail, you can add or subtract. You may not need all of these Sadat's year, month, day, hour, minute, second mini millisecond and whatever Z is, right? So I've seen this, used this very detailed. It gives you the exact timestamp, something happens. You may not need that level of detail that's up to you. And then the level what level warning is it is it's an inflammation warning. I'll go through that later on. What is the message? And then new line or exception, if there's an exception included and Bricklin and show the exception. Alright, so that's basically what that is. Doing. Experiments are that I have is rolling intervals. So that means what interval should that creates a new files. So that brings me back to that random dash dot, dot hub there. Because what's going to happen here is when I see rolling interval dot d means and without dash and the DID associated with each d. So this is good for segmenting your loved fast. So somebody said something up in the last week, Thursday. You can easily go and find the log file for Thursday off last week and review it. Otherwise, they're just going to end up with one big file that keeps on growing and growing and growing. And then you're going to have years of lugs in one file, which is to me that's inefficient, at least when you have multiple files, you can manage the older ones. You can delete them safely or move them to an archive safely and still keep that segregation. So that's why I'm setting that early interval. What do you have different options? You could do it by the day, by the hour, or by the minute, by the year, it's up to you. All right. The next one would be the restricted minimum level. So I want to restrict to a minimum of log event level information, right? Meaning I DO needs a C every little thing, there are certain debug points. They all, you know, this is starting, initializing this and reveal that I don't need to see all of that. So the whole verbose here logs are depends on how much you log, as well as what you set as the minimum. So here I'm seeing only log at a minimum of information. I need to include this library controller dots enter, and we include that library. And then I'm missing this semicolon. But before I put on the semicolon and take a look here again. So we're sure, and I'm missing a comma here. So that's a good thing. A took to review that. And then the final thing here to get rid of all of these arrays would be to, after this file open and closed brace, we say dot create loggers. So it's good to see a logger configuration on all of these. Create the logger object. No. Alright, so now that we have it created, we can actually start using it. So what I'm going to do here is we're up or start process or our mean, the main line in the main function inside of our track cash. And if you're not so familiar with that track gadget means is going to try to do something and if there's an exception, it will catch it and handle it accordingly. So that's what we'll call exception handling. Alright, so what we're going to do is to try and run this line. But before that I'm going to log to the information. Our login bits of information to say, hey, application is starting so we can see exactly what time and all the details required to know that the application started at that point. All right, if we catch an exception, and here I'm just qualifying exception with the objects that actually holds the exception, then I'm going to see fatal. So you can log error, I can login information, you can log warning. Here, it's feeds on if the application stops working. So I'm seeing in love not fatal. And I'm see and this is the exception that cause the fetal longed to be written. And this is a MRD and a C application on fields, fields to start. So I am seeing so that when somebody's reviewed the log, this is the result of or this is what happened. As a result of this exception. The logger will pharma Tito Nissl formatted and spit it out into the file according to this. Alright? And then after all of that, I'm just going to say finally. Finally means after you've handled or they had tried operation and it caught it and everything is done. What do I want to do here? I'm seeing, I just want to flush and close my log object. So that's what's going to happen when we start our application. So right, no, I'm going to go ahead and press this Play button up top here, which is going to start up your application. Or we can go to the log file and see what happens. All right, so now that the application is loaded and just so you can see, the browser will come up with swagger, will go through swagger and later on, don't worry too much. Humboldt's this, it looks nice, but our focus here is on our logs. So we see our log here. Application is starting now we see the log level and it's kind of formatted. Holy, thought it wouldn't be right. So other things are actually writing to the log, see their obligations started. So log data was started. So this is a starting, this one started. So you can see the exact time stamps for what that's worth, right? We know the environment, so you see logs provide certain details for us that we can't see when we're just looking at the boroughs are like this. You would never know that all of this happened in the buck grown just by looking at this. So that's it for us setting up the logger, at least for now, later on we set up our database and so on. We can come back and add the function that it can log to the database. Also. 9. Explore Swagger UI: Welcome back guys. So today we want to just have a quick run-through off swagger, how it ties into our API development and what its purpose is. So swagger really is there to help simplify API development for users, teams, and enterprises. It's an open source tool sets and it basically helps us to design a document our needs obese with much less effort than it would really take to have this level of detail. So it's a really good tool. It helps us still automates a lot of things. And the best parts of its odd is that it is already included with our API in previous versions, who would have to go and install it's granted it wasn't a very difficult process. Bullets note that Microsoft does seem that it is kind of a standard that everybody with an EPA wants to put Jian soccer because it's so cool, so efficient at everything it's doing. Then what they've done is they've actually just started packaging it in our API for us. So the main libraries that allows swagger to be integrated, well one, it comes from this new GET pockets. If I go to manage new get package, we'll see that we have the package already installed. Swash multiple dot is p and.NET Core. Alright, he was less disorder tools then in our startup. So remember that program.cs cause the startup. So startup is null where we define all the middlewares and the one that we have in the services for Sagar is services, thoughts, odd swagger, Jen, we put in whether or not we either way, if we were doing it manually, we would have to do this. But because it was generated, once again, we don't have that step. So it will generate the swagger and document. It supports versioning. So if you have version one, version two, et cetera, off your API, you're able to keep truck off the versions are at nice. Let whoever is reading documentation Norwich version off the API they're looking at, you can define certain open API inflammation. That is the title, the version. If I click comma here, you'll see that you again add contact information. You can add a description, license, all sorts of things. So your documents or somebody looking at your API documentation knows exactly who if you want to provide that level of detail and watch this API is of bolts. Later on. Further don't or other. In the Configure section, we have the use swagger and up use swagger UI. So the swagger UI means it will create its own endpoint to have its own kind of configuration file, and it will call its of hotel listing v1. No, right? And no, this is on the end is development. So n is just a variable that allows us to track which environment where in our early in development, when bread, milk, Schon, right? No, anything that goes in here. It's basically seeing. We're in development. So when we published this to say as your IIS or to the internet, whatever it is are wherever it is we put it, don't do any of this stuff. That's what this if statement basically says. No, I think soccer is useful. So while they may have put it in the development part, which I understand, I think that it's easier to just include it in the API at all times. So that when I published my API ADL and tough to provide as much technical support to somebody else to teach them how to use the API because that's what swagger documentation is for. So I'm going to just take these two lines all tough that if statement and place them in the general area where everything is is going to get done regardless of the environment. So that's my modification. Once again, context is everything I can understand that for security reasons or just general Lakoff need for information exchange. They probably said, well, you only look at it in a development setting because the developers may be internal. But then if it's for third party developers, then I'm going to make it external and publicly accessible. So let's take a look at one of our controllers. And well, the controller that we have, and you see here gives us the weather forecast and defense I get method. Alright, now if I run the application and the webpage comes up, we're seeing our swag swagger documents. Alright, so hotel listing version one, all of those were things defined in the startup. So if you need to change the name or make it more appealing, user-friendly, human-readable. You can always change it inside of the configuration areas here and here, right there it is, title. So if you want to add description, description, it will come up on the page. Now here it is showing us what is in the API and what's in the API would be our endpoint to get, right, going back to the controller to get weather forecast. Alright? So it's contextually generating this document based on what it sees in the project. And when you click that, it will show you examples of what is going to come back when you try to retrieve anything. Which is exactly right because this is returning a list of weather forecast and weather forecast. Terrorism is a class that has some data fields defined on each one has a date data type. So datetime, int, int and string. So you see if swagger is actually taking all of them, see the it is showing you're going to get MCA field called Beat temperature, sea temperature f. And summary is going to show you all of them. And it gives, even giving you an idea of the data type, Datetime. Int, int and a string. So I'm just showing you how powerful Sagar is without any effort on our part to already have API documentation, which once again is very important when you are going to be building on client application, consuming any API. Or if you are the one building the API, you make it easy for somebody who has to consume it. So the same way you'd want to be treated as a consumer of somebody's API to have all the information you need to know how to build their own it. You want to make sure you provide that information to persons interacting with yours. So swagger makes it out of the box very easy. And just to push the envelope a bit, when we go to try it's old, we can actually click Execute and swagger allows us to actually test our API right here. So these, this data that's coming back with the status code 200, we gets into all of that later on. But you see the response body. That's because it's actually executed the code that is here. And just to prove that if we click over and this p and we get this red dots, which is a break point. So I'm just going to click Execute again. And then you see Visual Studio pauses and it hits this breakpoints ac, you know, has this yellow arrow in it. And that's allows us to press FL f 11 and go line by line. So I'm not trying to show you how to debug NANDA showing you that this is not fluff, it actually will help us to test. So no F2 testing utilities, swagger and postman. Alright, so and I press F5 or I can just click continue up top here, whichever one, then it will just continue with the execution and it will bring it back. Alright, so that is whole swagger helps us in our quest for testing. Now I'm just going to do to fall on special and let's include or logger here. So up top, I've already, well, by default it's injected. So because we are using semilog as a default logger when we do logging using our object here, it will use the serial logger. So I'm just going to show you little snippets of hole logging hopes I can say lager dots. And then I would allow information to say accessed weather forecasts. Alright. So this is just inflammation to see accessible the forecast. And then I can see later on weather forecasts returned something like that. You know, it may not. This, this is an elementary bullet, is just once again, for example, Sikh. So just see logger. Blogger. Oh, well, I'm sorry, I put that to find oh, here's a return statements, so I'll just leave it as information for no later on we'll get to experiment whirlwind web or unquote attest to it. So I'm just going to run this application once. And then I'm going to go ahead and try it out. Click Execute. I can remove the breakpoint by just clicking. So as long as that red dot is there, it's going to stop when it gets to that line, you just remove the red dots and press F5 for it to continue. Alright, so executed. Let me see if my log is going to show me anything useful and mature and fan. And there we go. So this is now the log files all the times that we've actually opened it up and it did something you see here, it's right in the lungs. So here is our first blog application is starting and then it's logged data. This did that. And then here's the one that we just wrote, accessed weather forecast, right? And then it's telling you all of the details of what it's doing and getting an descended. Right. So that's all a logging works, that's all Sagar works. 10. CORS Configuration: Welcome back guys. In this lesson, we're going to be configuring our chorus policy. No, of course, is an acronym for cross origin resource sharing. And this is just a mechanism that allows you to allow our restricts. The sharing of resources across though means. Let me say that in a bit more English. When somebody who is not on your network tries to access your API, by default, your API has been to reject that access requests. Alright, so if I develop an internal API to be used in my company and somebody from outside my company with a completely different IP address and everything tries to consume the API or talk to the API, then it's going to automatically know that, hey, well, I can't send you any information because I don't know you. So we want to configure this policy to facilitate some conversation with sources are requestors. That's I'm not necessarily in our network. Alright, so I've actually run into this before where I developed an API for my company, for third party use. And I spent some time debugging why this company couldn't access the API that was clearly working on my machine and every other machine, our own B. And then after digging, I realized it was the correspond to c. So sometimes you leave an e-learning learned through experience. Well, I'm here to just let you know what configurations you can put in place from the get-go to kind of avoid certain busywork. So in order to add this policy, what we're going to do is in our startup dot cs file and I'm just going to add it here. Order does matter to some extent, but right now we're not really focusing on the auto would just wanted to get our configurations in. Someone's just say services, dot, add cores, and then just put the semicolon there. So when we say, of course, we need to add a policy like corps needs know-how to behave, right? So the same way that when we're setting up the other swagger Jin, sorry, would say See, and then this lambda R0. And then we can have multiple lines with multiple configurations. You'd see it's with endpoints and so on. We are going to be doing that here. So I'm going to see all you can use any tool can really doesn't equal b, c, o equal to the word options. Like I said, you see them using Endpoints stone here. So I'll just say All. And then the lambda R0. And then what I'm going to do is open and close curly braces. So that means I'm going to have a whole block of configuration on some this break in the line so we can see clearly exactly what sought. And then I'm going to say all dot add policy. All right, so I'm adding up policy then after giving it a name. So first parameter is a Ma'am, I'll just call it CORS policy tool, fancy or confusing. So CORS policy, then comma and then after define another lambda. So I'll just call this one build their cause normal to be building the policies. So Builder lambda R0 and I'll just break line. So I wanted to say a builder. Dots allow any. So here are all the options before I started sitting them. These are all the options you can allow. Nea can disallow, you can set. So if it is white listed or with certain headers, you can define hall. Your API will determine who is allowed to access me or my resources and who is not. Farnell for educational purposes. Later on, maybe we can look at the securing of it and holy mix and match. Well then once again, context is everything. If you're developing an API for internet and third party use, then you can't be too Street with the API if infrared anybody should be able to get on. Otherwise, you're going to have an administrative overhead of trying to figure out who is who all the time. So I'm just gonna say a low any origin. And I'm just going to chain along a low any method, meaning they can access every method that endpoint that's is defined here. And then I went to say hello, any head DAR, sorry, a low, any header. All right, and then close the brace for the policy and then use semicolon. So that's my course policy that are defined. So I'm DO siloing every and anybody. Once you're coming to access my API, you can go ahead and use the resources. Once again, context is everything that will determine how strict you are with your, your course policy. Now, after doing all of that, I'm not going to go down to configure. And I'm going to let the null that did should use the course policies. So right here, I'm just going to say use cores. There we go. And then it's going to say, okay, it does some overloads. I'm going to tell it the policy name C. And so just by putting the quotation marks, it's an old saying, okay, what's a policy names? So the policy name as I just outlined up top is coarse policy. So maybe you could make it a bit more informative. You could see a low. All right, because that's all it's really doing. This policy is allowing us, I'm going to say use the policy that says hello. All right, so that's what of course policy is really for. So this, in this situation, we're not went to fully see the benefits of it. But then if you done any other project where you have the API and then you have an entirely different project, which is the client projects, which means it is being broadcast at a different IP address than our port, than the current API project. Once they tried to talk, that will not work until you have this policy in place. 11. Review and Add Changes to GitHub: Welcome back guys. In this course we'll be adding or quote to source control and all source control is a wonderful tool that is used to help us keep track of all the changes that we're making in an application. It also helps us to work well in teams because instead of having 34 different versions off one project, the source control repository acts as a central storage area for everybody. It's a subscribe to check Ian changes compare against others, resolve conflicts, and many other benefits. So we are going to be setting up our source control for our project. And after we complete each module will just go ahead and check it in and make sure that we have consistent tree of all the major changes meet in our projects as we go along. So our tool of choice is GitHub, which is null Microsoft owns. So that makes it a wonderful tool. Easy integration on everything is wonderful about YouTube. It also allows us to host projects publicly so others can come along and see your work and help us, it helps us to build a portfolio of projects to be used for even our own resume. So if you don't already have a github account, you can go ahead and hit Sign Up. It's pretty easy to create one you just need a user name, email address, and password, and some verification and then you're in. So I already have medical and so I'll just go ahead and sign in. And I'm just giving you a preview of my webpage. You see the repository is to the left than people who have followed. It gives a nice newsfeed as to what people are doing along the way. Who is following you IQ and followed them. And it's just a wonderful tool to kind of build a rapport with other developers and general open source community. Now going back to our projects, what we are going to do is just add this source control. So the easiest way to do this is to look down to the bottom right-hand corner and you see that add to source control. So if we click that, you'll see gets and what happens is that you have a version of Git on your computer, but then we can also synchronize it with GitHub. So once you do that, it's going to say, okay, whereas the local path please sign in, you told is the primary destination. So like I said, it's Microsoft owned. The integration is very easy. So you can go ahead and sign in silos, add my GuitarBot cones, and I've already there second is authorized. And once that's successful, they had just returned to Visual Studio. And you see just feel load everything. The repository name, you can add a description someone to see that this is an educational Web API built using.NET Core 5. So somebody's stumbles upon it. They will get to a little just stuff. Oh, that's what some bolts. No, they do allow private repositories. Right. So if you're working on a school project or really something that's confidential, I don't want the world to be able to access it. You go ahead and leave that mock state. Otherwise you on ticket. So I wanted to share this with you guys. Leave it on ticked and then it will show you this will be the direct link to the repository. So I'll just go ahead and click Create and push. And once that is done, I'm going to go back to GitHub and Trend View it. No, you may find it easily here I have quite a few repositories to my left. So what I'll do is click on my display picture, go to your repositories, and then I'm going to see all of them listed kind of in the order that they were last updated, right. So here's my hotel listing and all of us are here, OTA listing the controllers, everything that I've worked on. So this will be the first chickens. So like I said, it keeps struck off all the commits. Every time we make a change, we can go and look at what exactly was done. And this was the first commit, so we didn't have to add a message, but later on you'll see that we can add messages so we can annotate each time we taking code and say, this is what happened in this version. So with that done, we've completed this first phase of getting our application onto source control. You can go ahead and add a Read Me so that people get some amount of instruction unless the whole To use your project. If it is something that is there for every n anybody to use. 12. Implement Data Classes and Entity Framework: Welcome back. In this lesson, we're going to start setting up our data classes. And by extension or database that we'll be using Entity Framework, which is cores flagship Object Relational Mapper or ORM for short. And they allow us to actually model or database classes are our database tables rather as C-sharp classes, and then engineer our database based on our class definitions. So what we're going to be doing to get things started is creating a new folder in our project. So just right-click, go to add and click New Folder and we'll just call this beta. Now inside data, we're going to start putting in our classes. So our hotel listing or well, APA will really, just for educational purposes, only have two classes or two tables, one for the country and one for the whole till. So basically when we look for our country, we should be able to see all the hotels that are associated with said country. That's basically the idea that we're going for, right? So I'm just going to go ahead and right-click data, click Add. And our first class will be country. So notice I'm going to name it in a singular fashion, country. The next one would be Hotel. So this each class represents one unit, country and a hotel. Before we start defining the fields for either, I just wanted to get all the files in place and then we can just work our way back and see how everything ties in. So after we have defined our classes, at least these two, I wanted to just go ahead and create what we call our DB context class, right? So I'm going to call it data base context. And go ahead and add that. And then this class is really going to represent our bridge between our defined classes or our entity classes and the actual database. So country, that's an entity that's going to be Ford engineered into a table, right? Whatever we define as fields will soon double back and do that. But whatever feels we put in country will be fields in a table called whatever we're caught it. So we're going to call the table countries, because the table is effectively a collection of records of type country. The same goes for hotel, and the same will go for as many other entities slash tables as you may have to define. So this is all we'll call code first engineering where we actually write all the code for a hallway, think our tables should look. And then forward engineer our make adjustments to the table accordingly. So after creating this database context, we need to kind of outfitted with things that it needs to know that it is the bridge to the database. So the first thing that it needs to know is that it inherits from DB context. No, this is going to give an error because I need to go and fetch some tools. But then when I control dots. You, you'll see Visual Studio suggesting that you install the missing package, which is Microsoft dot Entity Framework Core. If you're not seeing this prompt, NO problem. You can always just go right-click the project gotten, managed New gets, and then you can search for the same package, just go to browse and type in the package name and you would see it listed there. So I though on works, but while I'm here, I'm just going to get all of the libraries from here. That's I know I'm going to need, so I'm definitely going to need this library, so does don't load that one. And once again, I know I'm definitely going to need the driver for SQL Server because we'll be using SQL Server databases. That being said, there are other ones for other database engine so you can use a sequel light. You have, I've seen postgres not seeing listed here, not immediately, but they're all here. So we'll be using SQL Server. So I'll go ahead and get that one. And the final one that we're getting, at least for this period, is the set of tools because we need the tools to be able to run some commands in the future. So I'll just go ahead and install that one also. Alright, so now that we're done in New gets, if those salon to check over and installed, if you clear the filter, you will see everything that you have installed. That's fine. So I'm going to go back to my DB context and then I went to control and dots again and then the prompt, NO gene does still include the using statement because we already have the library at this point. Now inside a far repository, well, sorry, or database context, what we need to do is define a constructor. So I'm going to see public database context, or I could've just done see Tar tub, tub. There we go. And then I'm going to take the parameter DB context options. So this will be passed on from the startup plug. We have defined all of that yet, so we're just fitting it. Write null. And then water I need to do is also initialize the base controller, sorry, a constructor for the DB context to take the same options. For no, we don't need to put anything else inside of the constructor so we can just leave that blank and move on. So I did say that this represents the bridge between our application on our database. So it is here that we actually list out what the database should knowable it when it is being generated. So in shorter terms are more practical terms. I wanted to say a public DB set give this DB's data, data type, which in this case could be country. And then I'm going to give the property name, which would be countries. So the name that you'd give it here is the name that the database will use. So the datatype as far as C-sharp is Gunter, concerned is country. But then the database is going to. Define a table called countries and whenever we're accessing it will access it as countries. So that is a minor thing. I mean, everybody has their own naming conventions on people use a common letter for their table names. I don't like to do that. I like to keep my table names plural and the datatype singular because this is one country and what does a collection of countries after August is that dB? It's a set of countries no matter how you want to justify it, that's my justification. Once again, context rules everything. So I'll do the same for hotel and hotels. After doing all of this, we need to let our upsetting things no connection string. So the connection string is basically just as the name suggests, as string, that all lines hole to get to the database that the application needs to connect to. So what I'm going to do here is create a new section and see it's automatically give him a connection strings, right? And inside there I'm just going to call this, let's call it SQL connection. And connection is going to have Server equals and we have local DB that is kind of built into Visual Studio. So at this point, you may have your own database that you want to use. If, if not, you are a beginner and you're just following along them, you may use this one that's defaulted off to do much more anymore installation actually, it's already included with your Visual Studio installation. However, at this point, if you have like an SQL server localhost starting with an IP address, that's what you would put in as a server value instead of what I have here. Alright, but continuing, we also define a database names. So the database that we should look for slash create, I'm going to call it it's hotel listings. Photo listing on the score dd. Alright, so that's the name of the database that's I would like to interrupt with on that server. And then just one more very important are relatively important option which is integrated security. And I'll just say equals true. So that's all to our connection string. That looks like. So everything will come together after a while. We're just doing it bit by bit, building up to when everything is integrated. So our next step is to go over to a startup. So I did say that when we define a context, its getting its options from the startup. So the start-up needs to know that when the application starts, it should be loading its database configuration from here and using this file as the breach. Alright, so what we're going to do is add a new section. Actually, they may just three. Are they submit soul? I like to add controllers as last or near to the last thing I do in configure services. So I'd like to do everything else before. I add controller so you can just go ahead and move that line. So services dot DB context. Alright, so I call it a database context. The code, the functions is, it's looking for DB context. And then what did take spikes is something of type db context. So this is of type db contexts. This is my DB context. That's I'm creating someone's, we'll pass that in as that data type is looking for, of course, including any missing references. There we go. And then here's the part options. So that lambda initializer that were used to by now or it's not foreign to us by null. So for options, I'm going to say use SQL Server. All right, and remember that when you get those snow add intuited that SQL Server libraries, if I just control dots, you see here it seeing include the using statement, alright, so use SQL Server. And then it's going to want to know K. So where am I getting the configuration from? So I'm going to say configuration. Get your connection string, connection string. There we go. And then this is also wants to go. They're going to look at App settings. So it says give connection string because it already knows that there might be a section for connection strings. And I'm saying get the connection string with that name. So you can actually define multiple connections strings here you just needs a comma, separate them, and each one needs to have its unique name. And at that point, you could actually configure differently. It's obvious contexts for different needs. Our bases in the CME application, which could come in handy if you're API needed the span multiple databases. So there are a number of benefits to having an API because it's not limited to one deeds are based on one set of interactions, right? So get connection string. I'll go ahead and pass in the name closing all the braces that needs to be closed. And Farnell, I believe that we have everything later on we'll come back and modify this one. We need some other functionality added, but for no extra semi-colons. And there we go so far, no, we have all we need. Now before I move any further, I'm just going to double back and we're going to complete our class definitions. So we have hotel and we have country. So country. And I'm just going to say tub, tub is going to have an ID. So entity frameworks is if you create a field called ID, automatically assume that this is the primary key. All right, so you have two options. You can see ID or you can say the entity name, ID. It will automatically say, OK, well, I'll just use this as a primary key. Alright, so ID right there. That one is the key and let's say country also has name. So country name and one more slide. Just use control D to duplicate that line. And we see Maybe area or sharpening. That's just shortly. So in my case, the first sculpture that I would put in his Jamaica and the short name would be j m. And then based on the country, of course the short name is different, right? So those are the fields that I expect the country table to have when the database is generated. So I'm going to save that one and I'm willing to look at hotel No. So to start off, we can take and name because, I mean, we have to have the primary key. Every hole to has a name, but then I have some other fields here, including address, which is string, the rating which is a double, and then foreign key reference to our country. So let me explain this. So if you know about databases, you know that the primary key is a unique identifier for any given table. The foreign key represents unique reference or may not be unique, but it is a strong reference tool. Another record in another table. In other words, any hotel has to be in a country. So we have the hotel, we give it the name, its address, history, eating, but then we let it know. We, we give an ID here that corresponds with a country ID. Alright, so we have to define two fields. We have on data annotation here. So square, where IS foreign key and you give it the name that you want. So you could actually give this foreign key field at different name if you wanted. It's equal to manually put in your name or in this case, I'm just going to give it the same name as the class that it's referencing. So name off whatever class, right? Then we have two properties. We have country as an object, and then we have country ID as an integer. So country Id is the harder reference that's the ID valued on the tool does three et cetera. Whoever country represents the actual objects. So we can include all the details here. When we look at a hotel, if we wanted to know the name of the country, all we have natively inside of Hotel is the container ID. But then we can fill this object with all the details. So we can say Hotel dot country, dot whatever property it is that we wish to include in our beta. So this is nice and easy way to Juan creates a foreign key reference to another table. And to make sure that when we pull a query for a table that has foreign keys all over the place, we can include all the details right here without writing too many messy inner joins and having to jump through hoops to get included. It. So now that we have all of these details defined, let me just do a quick run through just to make sure we're all on the same page. We have our folder called data in which we are going to be storing all afford domain or database related objects and pulled all of that will be stored inside of this folder called beta. Later on we can look at maybe putting into in its own project. But for null, it's just three files are a few number of soil, we don't need to do all of that. So data has a file called Country, which is defining our country's table. And one called Hotel, which is defining the hotel's table. We also have the database context, which is inheriting from BB contexts courtesy of Entity Framework Core, which is once again acting as our bridge between already into classes and the actual database. Alright? How does it get to the database? Well, one, we have the connection string that defines where to look, what to look for and yes, look for its security, right? So that is our connection string. Otherwise, at startup, we want to add the DB context or add that bridge to the database courtesy off this file. And this file should be using this connection string. Okay, sorry, I just had one extra brace, just removed it. Alright, so let us do a quick build before we proceed to engineer our database. And to do a build. And you can do hold on Control Shift and press B, or you can go to build here and build solution. But we have a successful bill. So let's go over to the Package Manager console. If you're not seeing there, you can always go to tools and new get package manager and Package Manager console. Alright, so here is where that Entity Framework Core dot Tools Library comes in handy because it allows us to run certain commands here to facilitate the scaffolding. And that's what it's called scuffled into database, read the generation of the database. We have to run certain commands. So what we have to do is first add to what we call a migration, says it, add dash migration. If you start typing a press tab, it will kind of autocomplete. And then I'll say creation, let's say database created. Alright, so we add migration, B2B is created. So this is basically going to generate like manifest or a preliminary file to see that it is generating and CM getting an error. So this is good. It's good when we see these arrows and we worked through them because sometimes when we go through perfectly, we don't know what my topping. All right, so this arrow has to do with the country property in the hotel class. And I believe that tells us the ordering. So what I've done is to reorder it. So I had the idea underneath the property. That's what's it look like initially. So I'm just going to reorder by taking the property, the integer property, and putting it directly underneath the annotation for a foreign key and moving that don't. And so as you can see, can be sensitive our tomatoes with some things. So let's see if this works. I'm just going to rerun this command and migration. And we are getting a completely different vibe where it is seeing mill started succeeded. And that's enough snow that you've wanted to undo weekend around this, which means it has been done right? So here we have our migration file and then we see that we've got a new folder called Migrations. And what it does is take snapshots of each instance of the database. So at this point, we're defining our table countries with these column attributes and these properties. And if you look, if you look at it closely, I don't want us to analyze it too much because it can be overwhelming. But if you look at it as somebody who is familiar with the C-sharp language, you realize that it's not seeing anything out of the ordinary. Seeing we have a table or where creating a table, write the name of it is countries based on what we define in the DB context, right? Countries, that the columns in the table should be id, which is column of type int. And we're defining it as identity to increment by one. All right, that's all it's really doing. Name is a string which should be defined as invar char, because in, in SQL Server, a string is really invar char and short_name invar char, right? There. We're, there could be controls that we could put our own Maybe Day size and if it's nullable, right? But then those are things that we can look at later on. Ultimately though, we see here that we have our migration. And it looks good. So the next step would be to actually create the database. Alright, so what we'll do is go back to our Package Manager console and rho and updates the database and give that a few. And then when it is done, it will just NOW with a simple done. So how do we check? Go do verify. So you can go to the SQL Server Object Explorer. I have it open here. If you don't want to have it. There you go to View and you choose SQL Server Object Explorer. So in the Server Object Explorer, we go to the server that I did say it was built into Visual Studio, which is local DB slash MS SQL, local DB. Alright, so you can expand that, go to databases and then you will see the database listed there, hotel listing DB. And when we drilled on Andrew loan, you'll see our countries. You'll also see that they're tracking all of the migrations happening. So each time we make a change to the class that say, somebody came and said all, we need to extend country, we need to put on dialing code, right, or area of code, whatever it is, then you add a new field, you create a new migration, you update database, you will create one more 5A. This to say this is the change should be made and then updates obviously will go ahead and make those changes on your behalf. That's good in a development environment, in a production environment, not so much. There would be far more controls are on hold. Updates to the database are handled. Bought Farnell, when we're building from scratch, it's good to understand whole To do so efficiently. So that's it for no, what we did today was we defined our data classes are domain classes. We setup our DB context. We did all of this from scratch. Alright, and that's good. It's good to understand how everything clinics. So we have the database context, the classes or the DB sets, and respected memes, I remember whatever you call the properties here, that's what the table will get called. If you need to undo the migration, it becomes a bit tricky. Because if you just do a remove migration, you will get an arrow where it will tell you that the migration has already been applied. So you would have to revert this change to the database on a whole, which since it's in the Yom stages, you might as well just, you could actually just go ahead and delete the database, may get changes, create a new migration, and do an update database, right? So if you didn't need the database, then Entity Framework won't be only telling you that something has been applied, so I need to be assessed not there, it would allow inter move migration. You may get changes to whatever classes than you do everything again, add migration, update, and then it would scuffle the database with IA changes. Otherwise, if it is not as serious as are moving on migration, you just wanted to add or remove something. You go ahead and make your changes to your domain classes accordingly. Then you add migration, updated database, and it will take a snapshot once again at each point. So when we come back, we will look at whole weekend c, d, eta into the tables. Meaning when the, when the migration happens, we just put data in before we even get into the API because it's nice to have test data there before we start putting in data through our actual testing of the API. 13. Seed Data In Tables: Hey guys, welcome back. So in this lesson we're going to be going through a process called seeding. So seeding is where we provide some initial data to the database. And what we're actually going to do is just hard code some records that when we perform a migration afterwards, the migration will have instructions that create these records. Did the database with these records. And it won't necessarily rely on user input. So at least that will provide a nice basis for our testing when we start developing the API endpoints. So what we want to do is go to our database contexts and we're going to override a protected method that is really inside of the DB contexts. So protected over at void on model creating. And we're passing in the parameter ModelBuilder and I'm just calling it builder. And then what we'll see is some of the lab builder dots into dy. And then I have to specify which entity I'm dealing with soul. We have contrary web hotel countries self to exist, for hotels to exist. And that's really because of how we defined our red cards, right? So he said contrary and in hotel has a foreign key, so we have to have the contract before we can put in that foreign key. So we'll just say Entity, country dot has data. Oh, I'm sorry, I'm missing a racket peer there. Right. So entity contrary. And then open and close brace has the ITER data, sorry, open and close brace. And then inside of this we're going to define some conscious. So we can define as many because it takes an array, so it has the, it really takes an array of type country. So we can define a few records here. So I'm just going to define three. Alright, so new contrary required with ID equals one. And once again, we're putting in the data so we have to manually provide all of these values. And this is the first clincher that's I'm booting and short name is j m. Alright. And I'm just going to copy this and paste it. Kind of reduce the typing. So this will be two and this would be three. And the next one, let's see, Bahamas. And the short name for Bahamas, if I'm not mistaken, is B, s. And then the next one would be Cayman Island. Some does choosing some destination, some popular tourist destinations where you'd probably want to know what hotels are there, right? So the short name for Cayman Islands would be CI. Alright. If I'm not all that accurate, then later on we can acquire a kids book for null. Once again, these are exempted records, right? So I did that for country. I would just repeat that feeds for the hotels, right? So I'm just, I just copied MPI, is that most of the code. And notice when I change this to hotel, it's going to change the expected parameters to type hotel or whether it's seeing object because it's not getting hotels here. So that's fine. We'll just change these old photo. Alright, id name. What else did we have for the hotel at address? So let me get this. So this is some those resorts on spot. So I'm not actually familiar with some of them. Dress lets us keep it short and C and the grill. We already know the country. The country is Jamaica subculture ID would be one. All right. And then the raid team is last. I heard it was going to say 4.5, but I know it's a five-star kind of resort. So I'm just going to copy these details, don't. Alright. So we have a hotel for Jamaica. I mean, just put a hotel per country just to make sure that we're spread right across. And I'm just going to make up something for Sunda, far Bahamas. So Bahamas, let's say they have grand grand palladium. So I know for sure grand palladium is a hotel in Jamaica. But for example, sick, we're putting it there or puts it on their own police, I'm sorry. So this should be country tool, lets us do that. And that's a four star. Once again, this is not fuck to this making open data, right? So for caveman, they have comfort seats. And jurists, let's say George tone, the clincher ID is 34 cavemen and they're eating is 4.3. Alright. So that's a ceding some data into the database so this can get corroded. You would just collapse it like that. So it doesn't take up too much space. Or what I tend to do also is actually move it to underneath the DB set definitions. So that when I come to make modifications to the DB sets, I can always just stack them on top. I don't have to scroll all the way past that. There are ways to extract this may not affairs and call the configurations also. But then this is just a quick win, a quick way to see the data into the database. So now that we have defined a few tests to records, the next thing that we want to do is add a migrations. So I'm willing to migration. And this one we're going to call this ceding data, right? So notice that each die of ADA migration and I tried to be descriptive enough with the name such that you can tell, oh, that's what happened at that point. So it's almost like source control for the data, right? And if you look at this, this migration file, you'll actually see here where it says insert data into this table. And these are the columns, and those are the data values, right? So it will go ahead and do all of that, right? I don't know why I turn my four-point three to 4.299 and it not sure why, but that's how it is going to reformatted so that he can do the insertions. So the next thing that we want to do is update the database so that a can effectively carry out the commands in the migration. So it did said done. What I wanted to do is go back to my Object Explorer and then I'm going to right-click. And V would be on the country's table. And there we go. We have data in our database, so we have successfully created or three countries. And we can look at the matching hotels. Alright, so that is how you can put initial data into core applications using Entity Framework Core and the DB context. 14. Setup Service Repositories and Dependency Injection: Welcome back. So nowhere on the point of creating our repositories and what we'll be implementing is development pattern really. So let me just give some but grow and us to why we need to go through that. When we're doing our work with our API, it's easy enough to just write the queries using Entity Framework, Core and link. And we just write it especially like balloon. They have two tables contending with which our country and whole Ito. Well, what happens when we have 891020 tables? It becomes kind of tedious to try and write queries every time we have a table and then that's going to lead to repetition. And then if we have the same query multiple places, then that's a maintenance nightmare, R3. So that's why we are going to be implementing a pattern. And we'll be using the generic Repository pattern alongside the UN itself worth pattern tool kind of creates a container to define basic functionality that will be shared across all our tables and all our database operations in our project. So to get started, I'm going to create two new folders. One would be called i, i repository and the other one will be called repository, right? So we have I repository. And that's going to be a capital I. And then we're going to have another one that's I'm just going to call repository. So there's a concept called separation of concerns, where you'll want to make sure that you're ever file knows that it is doing one thing. So that's why we made sure to define two different class. For this, we're going to define some amount of individual classes along the way of what they wanted to make sure that certain things are generic kind were not repeating certain things, right? So in our eye repository, we're going to create an interface. Someone's creates a class because that's just quick. But I'm going to call it I generic repository. And go ahead and click add. And I'm just going to change so to interface. And if you chose interface that we'll be fine. The only thing is that you have to remember to put on public, right? So that's the other reason they're utils class was forgotten to put on public in the past and that could not understand why I was getting the arrow is getting. So that's my little fail-safe based on my experience. So what we're going to do is make this generic repository take a generic parameter and in the form of t, where t is going to be a class. Alright? So I'm gonna talk about generics. This t just says, well, I'm prepared to take any type of class that you send my way. And That helps us in creating those bees operations for different situations with different class types. Alright? So the first one that we're going to create a function called get Sowell gets. All right, so I'm going to say task I, list of type T gets, all right, and then I'm going to be defining certain things. So let me just explain exactly what is going on in this function header. So task, while we're dealing with a synchronous programming, we have to use tusks if you're getting an arrow, because you don't want to have that library that's highlighted there. Which points, you know, you just do controlled dot and we go ahead and into using statements. So task I, a list of type t, once again generic and the full SHA-1 name is gets all. So gets all has a parameter which for which I'm going to include the missing reference, which is of type, expression, function and expression, and we're making it an optional parameter. It's also going to take and I queryable, I queryable of type T, I ordered queryable. Alright, so you can just rewrite that Hawaii habits and order BY that's also optional. And then we have the ability to include if we need to. All right, then I'm going to have a follow-up function for get. So task T gets, so this one is going to get a list. This one is just getting one, right. So that's why it's task t and dishonest task I list. So this one is just going to get one record and it's taking the same shun parameter. And it's going to have the include so on where fishing boats, the, the actual function then you'll understand what the parameter is really stunned for. We're going to have similar formal Sean's for our crud operations. So I'm going to have task insert T and T D. So this is going to be the one to create. We're going to insert range. So I like to keep this one nearby. It goes sometimes out both operations. And instead of calling this multiple times, you could just define one that takes at least and it just those the wrist. Anyway, we have Delete and lead three-inch. Alright. And update. I don't like doing it though. The tree injury in the book, we have the update. So notice that the task that delete is task, all of these are thoughts, but these two are void operations. Alright, so that's it for our generic repository. So once again, this is being defined as b sketch on no matter what the data type, if we introduce five more tables and an accompanying domain classes, we don't really have to change much here because these functions would be fine to handle any other table our domain. Cost that gets through. And so knowing that we have the interface, I'm going to go ahead and create the concrete. So what's the goal? What's a repository class? I'm just timings on actual class and I'm calling it generic repository sub i generic repository. And no, I have just generic repository and generic repositories going to the same generic T. What is also going to inherit from IEEE generic repository where t is a GAS. I'm just going to go ahead and include the missing reference right there. And then it's going to company no, because once we're inheriting, We have to make sure we implement. So I'm just going to go ahead and implement the interface. And then it generates all of those methods stubs for me also kindly. So let us fresh. Oh, it's exactly what we need here. So we're going to have to do so and won't have dependency injection. So I've mentioned that if I have before, I haven't mentioned it much. Dependency injection is basically the concept by which whatever we loaded up in the startup is now available application whites. So we don't need to instantiate every time that we needed. All we do is make a reference to the already existing object because it was defined in our startup, right? So more contexts too early or connection are our bridge to the database. We can know, just get a copy of that to use in our file here instead of trying to create a whole new bridge, are holding an instance of this bridge. Kendall's leverage, the one that exists as a result of it being included in the startup procedure. Alright, that's, that's in a nutshell. What dependency injection read it helps us to do. So what we're going to do is define a private read only. It's private, it's read only because they don't need to make any modifications to it. And it's going to be an instance of data base. Contexts. Rights include any missing references. There we go, private read-only, and I'm just going to call it underscore context. All right? And then similarly I'll just duplicate this nine because I wanted to enter EDL Andy. I want DB set. Remember dv set coming over from the same database context. And it's going to be defined for a generic. So I'll just go ahead and include the missing reference there also the b set of type T, and I'm going to call this one dB. No, these are defined for this class. However, dependency injection NOW will require me to create a constructor. And it's going to take a parameter of type database context. And I'm going to change in the insula, the private one as honest scored this one does not. And then having taken that parameter, it is no, it's not accessing the one are the copy from the sides or procedure. So for my local use, I'm going to initialize my current contexts that I have my private read only to be the same value as the one being injected in. So that's pretty much dependency injection in case that was a mystery to your point. You know, that is how it basically works. There are other nuances to it. But for null, it doesn't need to get much more complicated than that. So the next one is on the score DBE is going to be equal to context though that I've initialized contexts. I can say context, give me a set of whatever t is. And remember that at this point, T needs still basically correspond with something that has been outlined in our dB. Sit, in our DAW is context. Alright? So that is why I can confidently say, go to the contexts and give me a set of whatever this is. Because a context shouldn't know about it by the time we're building this repository. So know that we have that part done, lets us go on to our implementation. So let's do the delete, which is fairly easy alone wins. This is var entity is equal to. And then I'll, I'll wait. So because they're doing asynchronous programming after a wheat. So I have tossed care. What I'm missing is the async keyword before it's alright, anytime you have a task that you are going to be using, o it nafta async, Alright, notice when a clique one, the other one gets highlighted, they go hand in hand. Alright? So you say, oh, it underscore DB dot find, and I'm just going to find it, find async. So indoctrinate core, sorry, in Entity Framework or for almost every operation you have a corresponding async operation. So at this point it's there, use it. And if you're using async, You have to precede it with await. And by extension, the method in which this await keyword is being used needs to have a sink on the method's stops. So it's not in the interface, it's not in the interface, but in the definition. And you have to have that. As you write more and more, you'll get the hang of it. So we'll find is sink and we'll pass in the ID for the record that we want to find. And then we'll say db dot remove. And we're moving the entity that hasn't been found with that ID. And that's it for our delete. Delete range is pretty much one line. It's just going to be db dot remove range. So we have a list of entities. So I'm going to say db dot, remove, range, and remover and says, well, give me the list of entities. Well, there's the only stuff entities just remove them. All right. That's it for the removal range. So I'm going to go ahead and To kind of go through the easier ones. So insert is easy, insert rage is easy and update is easy. And then we'll go back to the get and they get all cause those can get more complicated. So I'm just going to prepend each task in the method header with the keyword async. That one is voids. I don't need async there. Just make sure that I don't run into any difficulties later on. Alright, so for insert that one is fairly simple. All we're going to see is a weight db dot add async, and we add the entity, whatever came over as data on it. That's all we need to do, right? And then similarity for the insert range are going to do is db dot range async. So this one has an async, notice or move arrange did not have an asynch. Right. So at arrange a sink and the list of entities that you've got to add. And then for our update, we have a two part operation. One, I'm going to attach the entity to the db. So in other words, when the data comes over, it might not be attached or it may be an object that exists in memory with no direct connection to the database at that point in time. So I touch means pay attention to this and check if you have it already checked, if there's any difference between it and what you have in the database because the wearable to do an update, right? So then it starts trucking to see that, okay, there are certain fields that are different. So these are two different, let's say red cards, right? And then the next line would say contexts dot entry. And then we reference entity dot state is equal to modify it. So once we'd tell it that okay, it hasn't been modified, then it will know that. Okay, I need to do an update to it. So let's go up to our Git. Git is actually easier to do than to get to all. But once you do get, then get all omega a bit more sense. So the first thing that I'm going to do is get an eye queryable. I wanted to call it query of what's in the DB server. But dBs already defined to be whatever it is datatype that we're dealing with, right? So it does get all of the records basically that are in that table. Pretty much that's what this is going to do. And then I'm going to check to see if there was an includes. All right. Was there and includes requirement, meaning did the user are did the calling code, whoever called this getMethod, would they like to include additional details? So I did say earlier that when he comes to a hotel and country, instead of looking for the hotel and then getting the contra ID and then calling the database again to get the contract with that ID. And then that's two database cause you could make one database call and we're getting the hotel and including the country so that it will automatically fill this property with all the corresponding countries details, right, so that's what that includes is far. So this code snippet basically says that if includes is not equal to null, so by default it's not, it's optional. You don't have to put them value. If however you choose to put her value. If it is not equal to null, then for each property in includes, I want to include to the query whatever property was asked for. So they said country, then this foreach loop is going to run once. If you have five foreign keys and you put all five of them in that includes this, then this is going to run five times, including each one. Pretty much that's always going to do. Alright? So it's completely optional, but there might be times when you need to include on their Tanzania don't need for speed purposes, you don't want to include all the time for one query, for one bit of information when you didn't have to. So this helps us to keep the application kind of quicker than it would normally be if it included everything all the time. Then the next thing we want to do is return our weights query dot. And then I'm going to say as no trucking. So that's where that trucking thing comes in because any record that is retrieved here is not being tracked. Copies taken and sent into memory central to the client, the database and into different words are really terrible at it. So that's why I don't here we see a touch it so we get that record which wasn't being dropped. Two are being looked at and I always say start looking at it and just note that it has been modified by the time it reaches here, it has been modified. So we get as small trucking. But then after that's what I really want to do is get the first our default record and there's a first-order default async. There we go. And then I can see expression. So let me explain what the expression is. So expression is defined as Express on function t Boolean, and that's the name of the parameter. So this data that basically allows us to put tonight a lambda expression because then a lambda expression on would allow us to see some that IQ. And then the lambda R0 and then would say query dot something is equal to something else. So that's why I said bool, right? Whatever condition. So when we're want to retrieve the wanderer card, what is the condition that we want to use to retrieve the one Ricard? Is it by ID, is it by name? So this allows it to be very generic and flexible because then we can write or different expressions based on the context, but calling one method at any given time. Alright, so that's it for the next, for the, get, sorry. So the next one that we have to do is get all. All right, and get all is going to have all of that code with some tweaks along the way. So firstly, we're not going to be looking at any first our defaults. So let me just modify this era line. We get the query osmo trucking and the number is going to make it VO2 list is sink. Alright, so that's that, oh, it's 1-0. Calling an asynchronous function, you have to precede it with weeds. Alright? So we're turning our list. So we parse it to list as opposed to this one where we just got the first star defaults? No, we have the same parameter for the Includes, but we have another one for ardor bay. So I'm going to put another little snippets read after. Well actually I'm going to put tool snippets in. So firstly, we've got the query. Then I'm going to check if there was an expression, someone to filter the query first before I even look at it includes. All right, so I'm going to say if the expression is not equal to null because we could be looking for a list of red cards. But we want to say we're, the country is one on the sun. Give me the list of photos from Jamaica so we could put in the expression to see where whatever condition is needed to specify from Jamaica. And then if it is not, even if it is not equal to null, meaning condition is there, then filter the query for me please. So query is equal to the initial query which was all records d2, we're, that expression is true. Then after you've done that, because we could have had 500 and know the filter brought it down to 20. Then you go ahead and put on the Includes. Alright. And then finally, after you put on the includes and everything, I would like you to order if necessary. So if the person Boston on art or by oil wants it in descending or ascending R, this R that you just see if it, if the command came in, the inquiry is equal to R2 by query. All right, so that's really all there is that, uh, get on, get off. So we've gotten the majority of the work out of the way. We have about two more steps to go and then we are done with this task. So the next thing that we want to do is create that what I'm going to call that unit of work, right? So we have the generic repository knower when to give it the unit of work framework on top soil in ire repository, I'm just going to go ahead and add what will be another interface. So I'm just adding it on, I'm calling it i units off work, changing this to interface. And this one is going to inherit from disposable. Alright? And then what we're going to be defining in our units are four, would be it's going to collect our register for every variation of the generic repository or relative to the class T, Right? So right now we only have two tables to cater for. So I'm just going to see a generic repository for country. Sorry, for country. And include any missing or friends. And I'm just going to call it country is so different people have different naming conventions here. I'm, I'd call the contrary. Some people would say contrary repository or whatever I'm Claudia countries. Because when I call on the units of work, I can see this dot countries dot whatever operation I want to carry out. Alright. So we're going to do that also for hotels. Are hotel and I'm calling the property hotels. And then we're going to have one more operation, which is task C. All right, so when we're carrying out all of these operations, the IAB to update, we're making changes to the contexts. At this point. It's just staged, right? So when we see Save or Save changes, then it will be affected. So that is what this is for, but this is outside of the repository because if there are multiple changes to be made at that time, then all of them can be caught in one operation as opposed to making multiple costs or the database. So we have the units are for. The next thing would be to create the concrete class. So in a repository, we'll add class, call it unit off work. And then you add it up for work is going to inherit from i units O4. And once again, include any missing references and then implement the interface. Alright, so then what this is really just going to do know is say, Alright, you normal countries, what should I return when you call on countries from me? What should I call on here? What does disposed dual, what does saved? Those are the things that we need to define. So first I am going to include a reference to the database context. Alright, similar to what we had before. And then I'm going to define my constructor. C0 door. Try that again. There we go. And I'm going to put in the dates up contexts, those stolen to write to tote again. So I'm just going to copy their parts there and paste. There we go. So I'm initializing the data context inside of the unit cell for a cure and need to know that. Okay, I have a copy of the data of context also. So then they're probably wondering, so why do I need the contexts here? And that is really because what we need to do is return an instance of the Depository, but then we have to backtrack a bit. So I need to pray events the same way that we would have defined them over this side as privates. See if I can just do this quickly. So I'm just going to take that and I'm going to define two private properties of the respective Holt and countries, but don't want to rename them on when to take off the accessor. So this is going to be countries. On this one is going to be hotels. Alright? So no data how these private properties, I'm going to say though in here, that if the private property is empty, then return a new instance of the generic or depositors. I'm just going to do that chart on because C sharp nine is pretty cool. Second, it'll say something like countries and then question mark. Question mark equals. So it's music guy saying, if this is null, then what should I do since it off a whole if statement? Right? Now, just see if it is null, then return an object of the generic repository of type country. And of course, based on our definition off it's you need a database context, which is why we have it injected here. So we pass in the context. Alright, and then I'm basically just going to do the same thing for a photo. So this is like our register. No, this is just like a roll of the ecstasy that all of these are potential generic repositories on Syria and the unit of work I have access to. The contrary is the hotel's on forever table that you define. You need to make sure that you put Are you make representation for it in the I unit of work as well as the unit of work. But all of what we just did with the generic repository and I generic repository, we don't want to have to redo any of that with any other data table that we may add in the future, right? So it's just a bolt maintaining this list and these functions to make sure that we have access to what we need. Right here in our units, a fork register. Alright, so the next thing that we need to do, or well, two more things. So I want to define this pose and then we need to set up a Save and then we're done with this. So this pose I'm going to generate dispose true. So this is just the way I do it. It may see variations of the unit of work elsewhere. But this is the way that I have come to do it for various reasons. Once again, context is king. So what I'm seeing here is I'm going to call another method. So I'm going to define a method here, just that Visual Studio generates a method or aids on the Neith it for that purpose. And then I'm just going to say, well, actually, now that's I'm doing it. I'm just going to say right here on this floor context. So this pose is really like a garbage collector. He just seeing when I'm done are when the operations are done, please field the memory. That's the purpose. So DC here is actually sorted for garbage collector if you look at the description garbage collector. So this is saying when disposes called, then please dispose of the context and meaning killed any memory that the connection to the database was using, kill the connection, kill all the resources it was using, and go ahead and do what it would do by default anyway. So that's is it for the dispose. The next one would be our Save Changes. And this one is actually pretty simple because it's really only one line, at least right now where we see a weight, context dot save changes a sink. Here's the arrow. I'm seeing. Oh, it but what don't I have I don't have the async. Once I put that there, everything is fine in the world. So let me just draw built to see if I have broken anything or if there's anything out of place and have a successful build. So that means I've successfully put in the code for my units are fork, at least code-wise are syntactically. Later on we will find out if it works or not. But right know, this is a good feature to have and this task is done. 15. UPDATE - Strongly Type Includes for Unit Of Work: Hey guys, welcome back. So we just finish setting up our unit of work that was quite a bit of work and quite a bit of explanation and bucking and forth between a bunch of files. So I kept it simple. And the partner that's I'm referring to is the part with the Includes. So we kept it simply enough by just using a list of type string. And then in the generic repository we just implemented this foreach loop to say for each property that's in the string, then go ahead and include, well, right now we want to refactor that's a bit because the danger of having it in this fashion is that one. This is called a magic string, so it's prone to a typographical error and the compiler won't ever know it's a typographical error you might have inadvertently typed in SEO and TR Y instead of COUNTA RY, and then it would compile, but it would give an arrow once you hit this endpoint because Entity Framework Core wouldn't know what to do with misspelled property. Another issue might be that I might change this navigation property inside of the class hotel itself, right? What if I renamed it from just country to something else? And if I do that, then that would also lead to breakage when we, when we tried to hit the endpoint, not while compiling, so on to make sure that if anything changes in the code, it breaks something else so we can fix it null as opposed to later when a user complains of voltage, right? So we're going to modify the parameters inside of the repository. So I'm going to go to the eye generic repository first and we're going to change this parameter type tool. And I include a BigQuery table. So I'm just going to remove that list of string. And I'm going to put in that new datatype which looks very similar to the I ordered queryable, but it's I queryable of type T. And then it's I included the queryable and we're going to go ahead and include any missing references. So this is actually more like a function, right? So I'm going to do that for the ghetto, The Good PJ list as well as the Git. So everything is null going to be this more strongly typed data. Now as usual, anything that we change in the interface, we have to change in the implementation. So I just went ahead and updated these parameters in the generic or poster with the same data type. And of course we're seeing that we're getting a bunch of arrows at this point. So the first arrow is because we call it, I call these include, I called it includes before. Semantics. You can do that change if you want to or not, but that's fine. We're still going to check if it is null or not. So I'm just going to kinda do these changes wholesale, right? And then instead of a for each loop, what I'm going to do is simply say query. If it is not null, then queries equal to include, which is no, actually a phone Sean the inquiry. So in other words, it's going to see if I have content, then I will apply my inclusions to the query, and that is the new value of query. So that takes away that foreach loop and makes the code look much cleaner in my opinion. And that's it really for modifying our generic repository and I generic repository now inside of our controllers where we're actually interrupting with it. This is where the major change has to happen. So this method was including country. So I'm going to remove that. And what that's going to get replaced with. And I'll just name the parameter. So we know we're dealing with the include parameter. What that gets replaced with is a lambda expression. And so I'm going to say q dot. And then I would see include, include, which is a method. And then inside that method is another lambda expression. But before we go ahead, we need to include Entity Framework Core so we can go ahead and add that missing library reference, and then we can continue our typing with another lambda expressions. So look at it closely. We have Q or I'm starting a lambda expression doesn't have to be q, e could be, I, could be ink. Doesn't really matter. We know that by I know, but I'm just starting the lambda expression and then I'm calling the method include. If you look at it, you'll see that you have a bone Jia Trulia of almost every method available to you, but we're only focusing on the I include on the include. So Q dot include. And then we have another lambda expression inside of the include method where I see x dot and then I can see the navigation property relative to the class that we're about to query. So the importance here once again is that if anything changes into domain class, this is just code. So if I change the name reference here, then this country doesn't exist anymore. That's our red line. It won't compile. We have to fix it before we can push it to production. And that is the benefit of doing this kind of change strongly typing your includes. All right, so I'm just going to go ahead and let me get the contract controller. So we have a similar situation over here with our hotels and it will be the same principle. So I'm just going to put in that parameter include, include the missing references. And then this time it's hotels. So it's x dot and I can just see hotels that way. No typos. If I have a typo, then that's an error. If I put in something that doesn't exist, that's an error, right? So it's better to just use this strongly typed parameters. It looks a bit more complicated, yes, but in the long run it will meet Maintenance much easier. I'm just compiling to make sure that nothing else has been broken with that data and we have a successful build. So you can go ahead and continue and see you in the next lesson. 16. Setup AutoMapper and DTOs: Hey guys, welcome back. So in this lesson we're going to be setting up our data transfer objects and we'll be using ultimate power to kind of automate the process of linking our detail to our domain objects. So let me give a little background as to what I D DO are data transfer object is null. It really is a part of a pattern where we try to decouple our domain object, meaning Remember this is representing a database table. We try to decouple this from the user interruption. So it'll want users to be interacting directly with this class when they send and receive information through our API. So we have details as kind of like a middle layer which will enforce certain finally deviations at the front end part. And we can do quite a few things and it extends the flexibility. So we can use that to kinda sanitize the data before it actually gets over to our data class and by extension, our database. No, autumn upper is a library that will actually facilitate or creative or we'll call it mappings to say that this detail, much as this data class, Let's firstly tried to set up our data transfer objects. So in our project I'm going to create a new folder. And this folder I'm just going to call it models. The details are like model. So if you're used to using MVC or even Ariza pages or some other non-dominant body or we're familiar with the word model, i d t, o is just a fancy way of seeing a model, but it's usually used in terms of APIs, right? So you can name that folder models if you want to name it details so that you know exactly what it does, that's fine, but I'll just stick with models. Now instead of Foreign Models folder, we generally have a number of classes that represent each may be variation of a request relative to each domain object. So let's start off with countries. So country has three fields. Alright? So i'm going to creates a neat tool that will allow us to interact with contrary or have another layer. So I'm going to call it Country D T O, and that's my naming convention. I put on detail to the end of the same name, right? Because I don't want our coordinator here and conjure up there. And did I make a modification to one? And then it turns out it's always the wrong one. So by naming a detail, you can clearly see which one is not the DTU on which one is right. So go ahead, create country dto. Andrei Linde. Truly the dto needs to look similar tool, the actual domain knowledge you're probably saying, okay, so why the duplication? Because you just created another class in another folder just to give you the same properties. Well, at this point I did say we can add validation so I can see that the name is required, right? So that means when a user is going to interrupt with the detail, this annotation is going to say you cannot send me information for this dto without this value. So if it's not there, validation will hunt. We can also stipulate other things like. The string length. And then we can say maximum length is 150, or whether this is a country. So let's say no country should ever have a named longer than 50 characters though. I haven't done my research but lets us work with 50, right? And if I wanted to give a specific error message, if this was violated, I can't see error messages equal to corn tree. Name is too long. So if this validation for the string length for name is violated, then this is the error misses. So you can always annotate the teal such that when the user is interacting with the tool, wear, handling certain things to make sure that we're not exceeding are going outside of the band off what we want our data quality to be. After they have successfully gone through this validation. Then we will go ahead and do the mapping between the BTO and the country. So the principle is that the user wouldn't never see country when they will see the data class and the database would never see the detail. So users interrupt here. And then in the middle we transfer into d eta from here to here. I then pass it on to the Beats obese. So all the validations that we can add and just add that to short name. Here, I'll see a short name is also required on the maximum length for the short name would be to write and error message short name or short country name. And we say a short country name cannot yet, it's too long, right? We can always make sun much and GND Zope. There are other annotations that we can add along the way, but these two are the ones that's I'll use rational for the detail. Now there is also an extension or extending this butter and a little bit more where we create BTUs per operation. So when we start developing our controller, our controllers will start looking at the different types of operations on verbs and in what people do or are doing. Some cases that they have a detail per operation. Say I have a detail for reading the detail for creating a detail for updating. Because the reality is that there are some times when you don't need to provide certain information. So somebody is creating a country. I don't need them to have the field for ID, right? So the detail that's I would like them to interrupt with would be create country D tool. And you won't get that opportunity to provide a value for the ID because we really don't need the value for the ID. So generally speaking, have to have the country or I have the base detail. And then R14 created because once again, creates doesn't need the ID. Alright, so 1here, doing ar verbs, you'll actually see the difference between Hall. We use either one. I notice I'm putting it in the same file. Single responsibility parts are and can take precedence here. And you do each one in its own file like we did for the domain classes. Or since this is a small application, I'll just put all the details that are related to one domain inside off the CM foul dust in separate classes with their appropriate names. So I'm going to pause here and I'm going to challenge you to go ahead and do the same thing for hotel, creates the detail, and go ahead and put on some validations for the field. Alright, so I hope you took on that challenge and I am here to show you what I did know if you did it and you have no arrows, that's really good. I did it slightly differently. So I'm just going to walk you through the thinking behind what I've done here for the hotel dto. So I flip the script instead of creating the whole till, the till and then creating the Create version, what I did was I created the Create version and then I let it inherits the detail that BaseOne inherit from the Create and I'll explain that decision. Now going back to what we just did with the contradict deal, you notice that we repeated the fields, right? I IDs in one but not in the other, but there were repeated name and I actually refactor this one also we repeated name on short_name, right? So what I did was to say what are the common fields on? What are the unique fields otherwise. So ID, I only really need ID when I am going to do an update or I'm going to look at the details or something that's not a create operation, right? So I have the creativity to you, which is going to have all the fields that are absolutely necessary for the creation. They're also absolutely necessary if you're looking for the details or if you're going to be it. Alright? And once again you have variation. So if it is that you wanted a dto dot only allows you to update the name. And that's what you want to explosive use behavior to only update the name of the country, but not the short meme, you know, just for example, c_k, then you could create a need TO that says update country name, BTO, and all it takes poses is the name field. So you have all of those options. However, I'm not doing that granola into it. So what I'm doing is defining one where the ideas not prisons, and that's what we'll handle. The create operations are the non-ideal required operations. And then I have the base one which is inheriting from the one that has all the other fields. So the base one has ID and it's inheriting, so it automatically has access to everything that was defined. That way I don't need to repeat my validations because initially I had the same validations twice in the file. And for as many other details as I may have defined, I would have had these validations again and again and again. So that was my thinking here. So I extended that ideology. To the hotel details. So the create total detail, which has its validations for the name, right? And see I copied and pasted, I didn't even change this message. So that's hotel name is too long, address is too long, and you have maximum length. We can add minimum lent. You probably want to add minimum lengths, the short name, because they need to provide at least 11 character or even name. One character is the is needed, right? So coming back to a hotel dto, we have that validation for the name, validation for the address, the rioting. And let me just put some space so we can see where everything starts and stops. There we go. So for the rating, it's required. And I set our range of one to five because they're eating needs to be between a 1-star rating or a five-star rating. Of course, we're using double because you have, et cetera. So the re-engineer, Jill sees whatever numeric value is there needs to be between these numbers. And then the contrary ID is required. No, no what I have contour ID, but unlike the domain class, I didn't define country. And also missing from the creator is the id. So these two are missing because at creation all I need is the ID. All the database is going to see is the id. It's not going to see the actual entity or anything coming from that field. Know that field does become necessary, however, when I need to see the details, so like we describe instead of going and running another query to find out which country has the id that was provided here. I can just do an include and get the country details included. So that is why in the base detail, and I don't like calling this one the base usually inherit from the base. So when I said BS, I just mean the one that is not necessarily as specific for an operation. So I'm using it loosely, but I'm just explained myself so I don't confuse you guys. So hotel dto is inheriting all the fields that we're all lined in the Create version of it. But then it includes the ID and it includes an object of type country dto. So it would have been easy enough to just copy the fields over and you wouldn't be wrong. You don't need to specify a foreign key in the detail. Once again, that's customer facing. It's not database centric, so it doesn't really care if it's a foreign key or not to just says, Okay, I need an integer cause I was defined as an int. However, were not using Country because at BTO should never France a domain object directly. So Beatles topped the details. Doumani an objects thought to domain objects, auto mapper is the only bridging between the two. So technically speaking, a dto wooden doesn't even know that it has a domain object. So there should be no correlation with domain objects and id2. So the BTU is defined here, and the property here is also a DTU. So after all of this, I'm just going to do a build and see if there's anything out of place. And I have a successful builds. So everything seems to be no, seems to know where it's supposed to be. I'm going to just add two more things and then we can go ahead and install and configure auto mapper. Know, when we look for a country, it is sometimes easier to look for the country, or sometimes easier to look for the country. And you'll see the details of all the hotels that are a part of this country. So we kind of did that linking here where we're allowed to see the details of the country for any given hotel. But then when I conjure, has multiple hotels, right, we need to be able to say, look for the country with the ID one. And I want to see all the hotels that are there, which is not uncommon anywhere on the internet. If you look for, you know, on a booking website to look at Jamaica, for example. And it's going to show you the list of hotels. So what we need to do in our domain object, and we will be replicating data across also. But we need to have a property that is public virtual list and others use Ion list because that's an extension of the list data type. And it's a list of type hotel. All right? And it is going to be called Hotels. And we get to unset that property. So this property, when we don't need to do a migration for this, this is really not where to go to the database. This is just telling the domain object that when you are getting data for all of these, if it is request, then you can also include the list of hotels associated with the country. So remember in our units of work we did say you can do an includes. So would have included the details of a country with any given hotel. Or we could look for our country and include the list of hotels. So that's what that property is there far. Now what I'm going to do is allow the detail to actually have that behavior also. So in our country dto, I'm going to place that one inside of the nonspecific, non Operation Specific VT0. And once again, details speed to details. So hotel detail, that's the datatype we're dealing with. And it maps back to hotel. This doesn't need to be virtual. Alright, so we have a public where the potential to look at a country dto and get the list of hotels. Also, the field names have too much between the dto and our domain object if we wanted a mapping to work seamlessly. Otherwise, there are lots of configurations. I have to go and see, oh, this member or this property much as this one over that said we don't want to go through all of that based on what we're doing here. Everything should map to the other are two its counterpart, quiet, well, alright, so I've been seeing map, map, map, map. So let's install autumn upper cause that's what we're going to use to do this mapping. Alright, so right-click on the project, go to NYU yet packages. And then we're going to Burroughs and we're searching for auto mapper. And what we're really wanted to be ultimately upper dot extensions dot microsoft dot dependency injection because this one is specifically for dominate core that although on, it's not optimized core, right? So this is the one that we want. We can just go ahead and install the autumn upper is not the standard there, although tools out there that do similar things to autumn upper, but this one is very popular. I used lots. He does not failed me, at least in very recent times it has not. So we can get a lot of work done with autumn upper. So now that we've installed it, oh, I thought this on arrow. Now all we need to set up an initialization, right? So what I'm going to do is just create a folder. And you realize that I love to create folders is kinda segregates what is happening where someone's a call this folder configuration, xy configurations. And in this folder I'm going to create a class that's, I'm going to call it a mapper initializer. Alright, so we have to create that the configuration on class so that ultimate per knows how it should behave and watch it should pay attention to. So mapper, mapper initializer. And we're going to inherit from this class called profile. Now once I do that, I need to include the using statement for auto mapper. And then this allows me to create what I need to create a constructor. So once it's called it to undo the initializations. And then in this constructor, I need to define all of the mappings, right? So in other words, I need to see that this domain class called Country. And then we go ahead and include any missing library. Their goal is going to map directly to country the TOO. Alright, go ahead and include this. And then we open and close brace. And then I'm just going to follow that up with dot river smog, which is also a function. So this is saying that the country had Nieto class has a direct correlation or the fields in country needs a class as a direct, have a direct correlation to continue dto fields and they go in either direction. Alright, then I'm going to want to do that for all of the details that I have. So that's what I said. You can get granted. Oh, but once you get granular, You have to make sure that you're covering the potential mappings, right? So contrary to create and country to country, and then hotel to hold the T0. Alright? And then the same behavior or Cmd treatment for the hotel to the create Toto BGO. Alright, so now that we have the mapper initializer setup, we need to know, include it in the startup of our application. So we go to startup as usual, and then we are going to include a lion and algaes include it right here on the nice the ad core where I went to see Services, dot add, auto, mapper. And then this is going to require me to include something. Let me finish writing it though. First. There we go. So I need to include or had the using statement for automotive. There we go. So I'd ultimately upper and I'm going to see type off. And I'm going to pass in the data type associated with the per initializer. So mapper __init__ and get the spelling right laser. And then once again, include the missing reference, right? Include the using statement. And then once I do that, autumn upper is ready and we're going to go. So when we're actually developing or end points, we'll actually see the polar of the autumn operand hold the details, work and whole everything relates to the data classes, but it's good to get these configurations will tell the wave from early, so one, you set the standard for your application and to later on, there's not as much rework that needs to be done because that standard has been set, you're maintaining that standard as your application gets bigger. And all of these things are already in place. 17. Review and Add Changes to GitHub: Hey guys, welcome back. So we're at the second check in check point for our project. So after each module we will just review what we've done and then go ahead and update our repository accordingly. So it's always good to keep shorter Collins off your small wins so that if you're cold gets corrupted later on, you can always revert to the most recent working version of your application. So firstly, we can always know the changes that have been made by looking at the files are a deque means it was there and it is no different from the last thing that was kicked in. And a plus sign means that it has been added since the last chicken. So Git is always keeping truck off what the file looks like and letting you know that it's no different through door at dick are letting you know that this has been added since the last time. If you wanted to see what does change, you can actually right click go to get and you can see View History or compare. So when you do compare you to say, well the last version I had is the lefts and pages get my bearings right? So the allows version I had is to the left and the new version is to the right. So it will show you that this nine was modified in that way. And everywhere you see a green highlighted means that something happened. So when working in a team setting though, it's always recommended that you guys don't work on the seam files to check in because then if you modify something on your sad I modified that same file on my side, then we'll end up with this crushing kind of discussing situation where it will say, Well, the two lines are seeing two entirely different things. Which one should I use? I'm not going to have to manage what you call Conflicts. I'm quoting by mass Osaka really show you any conflicts aren't No. But hopefully you guys don't encode into that. So what we're going to do is check in. So to do that, I can right click go to get that is incorrect. Changes. There we go. So maneuvers and I'll Visual Studios at different layouts. We just don't want to get changes. Once again, if you're not seeing that, you can always click View and you will be able to see that menu item accordingly. So you always want to put in a message that depicts what was. So my message is the mean telling whoever would see the sicken, I didn't database autumn upper units off for on the deal. So you don't need to be, you don't need to write an essay. But at least let me have an idea or whoever have an idea of what you've done. After that, we can click that car it. Then we say commit all and sing. So it will commit the changes one, and it will prompt you to save, just play it and save it will commit the changes locally and then it will kind of synchronized with GitHub. And at that point, if there are changes waiting on the other side, meaning your team member made some changes and check them in before. When you say commit all unsinkable push up your changes, get the latest ones. And once again, if you do modify the same file with different content, that's where that conflict might come up soil. If you don't do that, then this is a really seamless process. So here we'll let you know that it was successfully synchronized and you can move along to the next task. 18. Overview - Setting Up GET Endpoints: Welcome back guys. At this point we have basically completed at least the bulk of our configurations. As we go along, we may see the need to include other things. But right now we want to start actually making our API work because outside of hitting F5 and seeing swagger and seeing the lugs, nothing works, right? We don't have an API just yet. So what we want to do is actually start configuring our get endpoints. And I'm going to explain exactly what the get endpoints mean. So to start us off, we're going to just look at this weather forecasts controller that came with our project. But it is actually just some sample code that kind of provide some context as to what we need to do to get our get end point up and running. So our controller, and like I said before, actually controls what happens when a user requests inflammation and teach the controller. The endpoints are usually determined by, are what we'll call axons, which are these functions that are going to be defined inside of the controller. And what it responds with R when the controller the options, it's rather it does it computation and then responds in a manner that the calling application or the client application that is trying to access the API will know that this was a successful call. Maybe. And generally speaking, whenever somebody cause I get to commodities in order to retrieve information, hence the word gets, they're getting something, are they expect to get something? So within the context of this sample controller, we see that we, when we call this endpoint, it is going to return data. So we are getting beta, granted it is very random data. It's nothing too serious. But the reality is that it is the simple command which is getting, so we have what we'll call this HTTP attributes, right? And it is seeing, it is defining the behavior of the function. So when we actually test results, and we can do that right here in soccer, and you just go ahead and pull this down and show us all of the examples of what we might get to eat. Then click Try to Toyota and click Execute. And then it's going to know show that this was the request that was sent. So notice there is no real indicator here to say, oh, this slash get there is knowing the kids and to see what the end point was, we know the server based on the fact that when we run the application, that's our server address. And then we know the controller that we're interacting with weather forecasts, right? That's the name of our controller. Weather forecast controller is a static keyword ever controlled and SSI naming convention. But then I don't know which acts on it, it, So what really happened is that, and I'm just going to set a breakpoint here so we can see now when we click execute, it actually hits that breakpoints. It's calling this method. And it's called Get. And when I press F5, it just returns with all the information that was being retrieved from that. So what's really happening here is that based on the protocol and certain definitions that we're going to be making here on each option. The way we formulate our requests, it will, the control will automatically know which one we should hit. And the context for this outgrown behind this is that you don't want to get too granular with your names for your actions you don't want to see and get 4x and get one, gets one by ID, get one by name. You can call, well, you can actually call the axon, basically anything you want to say. I can give it its own name. Of course, there are standards are owning that. But the reality is that if you have multiple gets eaten, name all of them to see him get. But you, based on the data that is required to retrieve the information, you can stipulate which get should get called. So all of that, once again, this is just the introduction. So, and in the next video we're going to create our own control. Now we're going to start off with the hotels, sorry, with the countries. And we'll see exactly how it goes and you want to retrieve the country is the listing of countries from the needs of its through an API call. 19. Construct GET Endpoint: Alright, so now we will be constructing or first controller and our first GET operations. So I'm going to right-click controllers, go to Add controller, and then we're just going to do an API empty controller. So this choose API to the left and API controller dash empty. And we're going to click Add. No, just for some clarity. We have gone ahead and abstracted a lot of the database operations into our units of work so that we're not directly interacting with our database through our controllers, right? If we did API controller with actions using Entity framework, then it would actually generate a controller which has an active object off the DB context, which is the database connection. And we would be able to do all of our entity framework work right here. That danger off that however, is danger in the long run, it may become less maintainable as the requirements girl, because then you're going to end up repeating a lot of cool, which is why we went all the way over to R i unit off work, abstracted away. All of that made it very generic. So that we have one code base that we're just making more dynamic calls to. So for now I'm just going to deal with the M21 because we really don't need to go ahead and scuffled this one aught. But as we build out the application, you will see the practicality of all we have done. So a PI controller dash empty, go ahead and click add, and then the name. You generally want, once again, the neem till it reflects the endpoints because just like with weather forecasts, we don't watch out when we heat URL slash weather forecasts. We expect to deal with weather forecasts. So if I expect to be with the hotels, sorry, I'm starting with clincher is I keep one single dose. So we will have country are, say countries controller. Alright. I wanted to say country. Alright, country controller. And then we get our blank controller. No, I look about grown behind what you're looking at in this controller, the root. So we have two routing mechanisms that we can use in APA development on this MVC API development. One is the convinced on base routing, routing, right? That one is where we actually have to go to the startup. And we would configure in US endpoints. We would kind of configure our roots. So Quincy endpoints, dots, mop, controller, controller roots. There we go. And then I would kind of define the naming convention. So I could say name, colon, and I'll just say a default. And then the Convention for the routing would be the pattern. Watch should look like. And I'm just showing you this is not the one that we're going to use. What's I'm just making sure you understand exactly all the options that are there. So we will have controller and then the sample would be equals home, right? Slash auction. And for example, index. And then slush. Any parameters that would be required are not in the form of the ID. Alright, so this should be encouraged in braces also. So this would be our way of defining convinced on base routing schema. That way, anytime I request comes in, that request needs a specific Alistair that we're looking for disk controller by that name. For example, weather forecasts controller, or does an endpoint we hope to look for. But we want this specific actions. So I did mention that we don't want to get too specific with our actions. We don't want to say get countries, get country, country by name, get to contour by, you know, we just list them all 1250 auctions. And then the you were calling client up against on us to remember the axon to be used with each call. So that is what this would kind of force us to do so far. And, and that's, that's probably more useful for a web application in our regular MVC application. But when we consider Arrest API standards, what they want is for the verb to determine what it is that you are going to be doing. So then we are going to be using what we'll call attributes rotating, right? Which is basically just going to say, look for the controller. And if we wanted to modify the sequence, say api slash controller. So whatever you put here, What's it going to come after that server names, server name being localhost, colon, whatever port two of slash, whatever route is here, right? So if you look back, got weather forecasts, oil where weather forecast, that's what's there. So it was that slash the controller being weather forecast. If we look at our new one, we see that we have slash api slash controller. So then the links will look slightly different. So when we generate the soccer doc, you'll see that coming to light. But right now what we're going to be using is the attribute based routing. Alright? So it's allows us to map directly to our controller and directly to the actions at all being too specific about which exact one. But then the verb is going to determine what endpoints should be called based on the request underneath. So now that we've gotten all lit up but grow and let's actually wire up offers and get. So before we can do anything else, we have to include our privates read only i unit of work so that we can take advantage of the database access. All right, and I'm just going to call this one on the score unit of work. So this is my naming convention where I use an underscore and you'd see it is to use an underscore for private variables. And you'll see as we go along, so we need that. And I'm just going to put on the logger. So I logger for that, we need to go and setup or injections. So I'm just going to quickly copy and paste these so that I don't have to monetary typing to do. So. Once again, dependency injection means that once we have registered and on that note, we need to go to the startup and complete a configuration. Well, once you have registered something in the startup as a service in the bootstrapper, it becomes available to four in injection in any way most cases, right? So far our controller, we can inject the instance of the unit of fork and we'll just make a copy of it to foreign local use. So that's what this is four. And we'll do the same for the logger. Alright, so we have our local copies of those. No, the thing that we need to do in a startup is to actually register the unit of work. So we create an interval, we did a register it in the bootstrapper. So I'm going to leave it and I'm going to show you the error that you would get and then we can resolve it together. Alright, so moving on, after doing those preliminary things to configure my constructor, I'm going to define that I want on HTTP. And you can see all of the potential verbs being listed there. So HTTP Get operation. And to complete this operation, I'm going to be using public. Just going to go async. So public async, task of type axon results. Alright, so if you, if you had generated the controller with the, with the Entity Framework, are they added to it? All of them would have been tusk of action results. So you just get to async code of the block. So it's good to just start using lseek from the, from the get-go right now I can name get country. All right. That's fine. I mean, well, in this case I want all countries, so countries because I'm getting multiple, right? Once again, based on our routing, we don't need to specify that. Well, you see that later on. And then our task null is going to do a try catch. All right, so we're going to try and operation and handle any error that we might get. And I'll extend this with x so that we are actually catching the exception object. And then here I'm going to say var countries is equal to o or unit off work to call the countries. And then I can say, get all. Alright, it's looking good. Now remember with our, our method, we could put in and experts on here if you wanted to add a filter and all get companies where we could do quite a few things from this method alone, but right now we just need all. Alright, and then I'm going to return. So the return types are very important. You want to return all key when everything went to our, alright, that's why it's called okay. Or 200. So to start those number is 200 and we can return the old kid with the data. Alright, so that looks good. So far we're going to be modifying it up bit fuel, but that's what we're going to try and do. And then if everything goes okay, we'll return. Okay, and it's going to send back to the calling client whatever data came back from this call. Know in our catch, at this point, our logger becomes very important. So logger dot log error. And then I can see something like dollar sign. Something went wrong. And I can see I can put in more details in the and someone's use my interpolation. Does that dollar sign there in case you're not familiar with it, don't assign string. He done those meant to super impose any variable at this point. So I'm just going to kinda specify the name off the method where whatever went wrong, alright. So name off get countries. Alright. And then I'm going to boss in the exception object. Actually I have that backwards. The exception should come first in log error, exception comma, then something went wrong with our exception, then our message. So Assyria log with actually just thresholds are printed out the entire stack trace. So you can see all the details of the arrow from the exception that has been true. No, if there's an error, I don't want to just throw what I wanted to do is alert the client that something went wrong, Lee, So yes, the logger see is it that's for all internal purpose. But then I want to return something the user to see, you know, this is what happens. So a status code 500 is the universal code to see there was a server issue. Alright, so this is telling the user that this, something went wrong on all apart. It's not you, it's me. All right. So then the status code 500 means Internal Server Error. And other say please try again later. Alright, so that's what our clients are. Look can I and consuming the API will see when there's an error. Otherwise they should get the list of countries. So let us test this out. Alright, so the first thing you'll notice is that, no, our new end point has been added to the swagger. The second thing you'll notice is the difference between Holden links loop. So slash weather forecasts for ourselves slash api slash country. Once again, that has to do with the route that we have defined appear whether it's api slash controller or it is just the controller name. Alright, so it's, it's dynamic. So at any point we can go and remove the API if it's too much of a bother, but we'll leave it for now. So let us see it, try it out, and then we click Execute. And what do we get? So firstly, That's the request URL, so the server, Alright, slash api slash country. And we're getting this error, right. So it's actually spitting out Tool or swagger the entire response. The sea unable to resolve service dot activating this dot and you see that it's getting up 500 error. Alright, so we told it return a 500 whenever something bad happens. And the other thing to notice though, is that I'm not specifying the name of the function being called. So before we fix that error, notice I'm not saying slash api slash controller slash get countries. It is only calling slash api slash country. You, the user doesn't know the name of the method being called and being, you know, sending back the response. So that's another thing that when we talk about the routing convention, because we specify that it's, i get it automatically formed. It ought to be a Git command. So we're going to fix the era and then I'm going to test it again using Postman, which should provide a little more context as to what we mean by GET versus post, et cetera, et cetera. So to fix this error, we need to register our service and I guess it before in our startup, not cs. So in the startup, we need to say something like Services dot and add transient i units or four units of work. So you would see the different school options are transient, add scoped, and add the singleton. Yes, sometimes I forget, right? So add the thing we've done, an add signal TA1 before, nor we haven't. Alright, so I'm trans. It means that every time it is needed, a new instance would be created at scoped means that a new instance is created for a period or for the lifetime of a certain set off requests. And add singleton means that only one instance where they exist for the entire duration of the application. So based on your needs, you might end up doing different ones. So add transient here means that whenever somebody hits my control, I'm going to always create. This is always going to provide a fresh copy. The IU and it's off work. So let me just go ahead and include the missing references. And then let's try that request again. So this time I'm going to use Postman to handle this request. So I'm I'm still going to try to vote only to show that. Okay, so we're getting an error for the logger. And okay, let's fix that. So these are, it's good to see these errors. Dc can tell why. We can't. We can track those shoe to Y where getting those. So I think the issue with the logger is that it has to be injected with the context of the class is being injected into. So in this case, it would be the controller. So I'll just swap this Alyssa I a logger within the context of this change where we see weather to conjure con Schrodinger. Alright, and then let's try it out once again. Alright, so we're going to try it with postman this time. So I'm just going to enter the request URL, which once again is just the is the localhost colon, the port number that you have. And then slash api slash country. No one would talk about GET versus post versus spots. Boltzmann, we can actually try to change the type. So remember that we built it to be, I get that's what it is designed to be. Which means that if I attempt to call this same endpoints without post, it's going to give me a could not get response. And OK, I'm getting something because of the SSL. So you can just go ahead and disable SSL verification and if you're getting that issue, alright, there we go. So method Mata load. Method Mata load means that it sent some request and the verb that was requested. Those nuts exist. Alright, so if I had tried gets and then send again nonce, I'm getting a 500 and I'm getting another arrow. Alright? Oh, we're getting some good error. So this concept of good errors, where it's good to see these errors and understand how to fix them, right? So this one is saying that System.out takes dot JSON is giving an exception because a potential cycles detected. So the buck grown to this is that because of the dependency on hotel, Hotel has a dependency on country on country. Has that dependency buck to Hotel. Once it is saying is that well, I'm getting hotel which has contrary, I'm Andrea's hotels. I'm seeing lots of data how going from side to side. So I'm, let's fix this one. I've encountered this one before. So let's just go ahead and fix this. To do that we need a library, manage, do get packages. And we are going to be getting the new soft dot JSON library, but not that one we want. The Microsoft is b-a. Let me just type in new turn soft. That's not the one we want. We want this one, the one that is optimized. For our purpose, right? So I'm just going to go ahead and install out1. Alright, and once it has been installed, what we need to do is go towards startup. And we're going to add controllers. We're going to add new TEN soft JSON. There we go and define some options. So all lambda RO, I mean you can call it option if you want any. Tolkien is fine. Lambda R0. And then define that OP dot serialize those serializer settings. Dots reference, loop handling is equal two analogous lions, so don't get too far off screen. So the serializers settings dot reference loop handling is equal to Newton's soft dot JSON, not reference loop handling. And then that's an enum, so on to say ignore. So where you see that, we're basically seeing where you may see a reference loop happening. Don't know, make a big deal out of it, just ignore it. Turned a blind eye. Let the program run. Alright, so another thing I'm just going through and correcting any little mistakes that are made here. We're calling get all what I didn't do was awaits a cardinal rule whenever we're calling an asynchronous function or something that's a task, makes sure we are weights. All right, so let's try this again. Alright, so going back to postman, we're going to try and send on more. And this looks a little bit better. There we go. Status 200, okay? Alright, so once again, our status 200 is a universal sand that everything is okay. And instead of us having to say status code 200, Knidos gave us a method for it's unfortunately they don't have a method for the FIFO engine or at least I haven't seen one as yet. So that is why this one looks that way. And we can just say ok, with the data to be returned and it will automatically be serialized into. There we go. Alright, so notice that we have each property coming back and hotels that's empty, Farnell, right? Because we didn't include the voters. What we can do that later on. So that is how we handle I get no 7x one more modification to make and that is to do the mapping. So remember that we don't want to return the actual domain objects. I was right, no. Gets all is returning country. And country is the database object. What we want to return is the dto. So we want to return, contribute deal. And then later on we will see how we can extend the detail to be a bit more, make it make sense as to why I'm going to go through all of this shovel because clearly the data model that the domain model as a return type worked. But then we still want that segregation. So I'm going to just say continuity or we're going to map to it. So we need our Autumn mapper in order to do that. And to get autumn upper, I have to define a privates read only called off type. I am upper, so I'll just go ahead and include that and then do the injection. Alright, so we, after we injected, then we are going to separate the subjects. So we're going to say var countries is equal to that call. And then I went off another variable under that and call it via results is equal to mapper dot map that I went to specify the data type I want to map it to. So I want to map it to our list of type country dto for which I have to include a missing reference, alright? And disclose that angle brackets. And wartime mapping is countries which is already coming back as a list. Alright, so whatever data type it is that you're, you're getting back off to make sure you map to that appropriate data type and then all of that. So there's just going to take all of the domain objects and convert them into country dto objects and stored there. So if I didn't specify ion-list, I would get an error because this is a list. And I'm trying to, well, it would, it would give an error regardless, it may not give you a syntax error, but you can see that the data type is not quite what I'm expecting because I need that list, right? So just be very explicit in set off this map section. That's your mapping. I list off this, or you're getting that I hope to map it to a list of that data type. And then instead of returning, the countries will return results which is of type Country D TO. So at this point, if it is that we wanted to leave off some details are include more details. We could have defined those additional fields in here, don't whatever calculations wanted to do in here. And then they would never really see what's in, what's coming directly from the database. What we would've sanitized it, transformed at, embellished it as much as we want before we return the data. So let's just go ahead and test and make sure that this one works and then we're done with this stuff. So back to postman, we're going to say send. So it's going to hit the same method. And right, no, it's bringing back. So here's proof that is bringing about something different because remember, hotels was at the bottom of the list initially, no ID hotel's name than short names. So you know that that data is restructured only because the fields in contradict you are in a different order than they are in the domain objects. Either way, we can see that it's still working and this is how it really should be. So when we come back, we're going to look at how we can get specific country based on maybe the ID. Let's start with the id. 20. Construct GET By Id Endpoint: All right, so previously we configured our get method, and this is really like get all method, but it's not all the time that our client application wants to get everything. Sometimes I wanted to get specific data, alright, so we want to at least provide them on end points where they can get one country based on a particular unique identifier. In this case, the ID. Alright? And just for context, since we're billing to API with the context of that client. If you saw a list of countries and he wanted to see the details off one of these countries and you click view, then what would happen is that it would go back to the database and get that specific country to display the specific inflammation are details of that particular country. Alright, so that's the same thing that we want to provide an endpoint for. So that when on their side, when the user clicks the country, they in the bug-prone, we'll say which country was clicked here, which IDs there? Here's the ID API. Please may I have the details? And then we say, OK, we'll do the lookup. Here are the details for that particular country. So without any further delay, lets get to it. So I'm actually just going to copy that original get. Alright, and we're just going to make some minor modifications. So the first modification on would be the attributes. So yes, they're both and gets, right. But this Get in particular needs to know that it can take a parameter, alright? And this is really, it does a lot to do with documentation on purposes on its wood so that when people see it, they can infer at the same time watts how it differs as it goes along. So you can define the Git, but then you open and close brace, and then inside that you define the template for the good. So I can say here that I am expecting some environments are called ID and it should be of type int. So if we wanted to get by name, we could do something like name of type string. All right, so, so you know that this get is going to take this parameter name. And the names are very important. And that datatype, which is also very important. Next, we're going to have to rename this. I mean, get countries, this isn't getting countries, this is getting a country. And it is taking a parameter ID. So like with any other method in anywhere else in c-sharp, once they're calling a method that has environments are in, you have to defend apartment that that's it's expecting. And notice that the name here, much is the name that is in the attributes. Alright, so get country ID, null. We have the same try-catch. Well then we're going to change the query and the mapping objects. So one, we're not getting countries where getting country and work on it in the same way. It's units, all four countries, what we're calling the get method. All right, and our getMethod, notice the red line, the get method requires the expression are the stipulation behind what exactly it should be getting. So we have to define in this expression. So remember I said that the expression is really going to be a lambda expressions. I'm going to pass in that same kind of lambda expression. Always say Tolkien lambda R0. And then what am I looking for? Q dot. And then I've all the fields off the table. So this was designed for countries, right? So what's field in the country's tables should I be looking for? I'm looking for an IB. And my my condition is that the ID in the country's table matches the ID coming in through the parameter. Alright, and then in the same way, I can include, because I'm just thinking about it. If you ask me for the country within the context of this, somebody clicked on a country. I figured out maybe you will want to see all the hotels for that particular country. So while looking at the list of countries, you only wanted to see maybe the list of countries. However, when you look at one country, you probably want to see the whole lotto, right? So our hotels, so I wanted to say a new list, someone's Abbas in a new list of type string. And I'm going to add to it. So this is all we initialize a list and a we can say that I want to include whole tos. So once again, this is now going to go over, it's our units off work is going to hit the, let me find the method which is in the generic repository. And it's going to hit the get. So this is the expression, this is the Includes. So it gets all the red cards. Then it says, if there is an includes, go ahead and include whatever you need to include, include the hotels, right? And then we're going to look in the query, take off the trucking and return the first star default to require that much is, and default really means just returned Neolithic affinity. Well, the first record that matches this expression, so they express on would be where q dot id is equal to the ID value. We'll do all the computation and just return. They want Red Guard took country with all of the hotels that are available. So I'm just going to double-check with my domain just to make sure that the thing is called Hotels cause this system much just the same way in the conscious ETO, it has to be called toes. All right, so now that we've done that wiring up, I'm just going to change up my mapping. So I'm getting about one country object, juan objects. So I'm not going to come up to our list. I'm just mapping to contribute teal. So that's a one-to-one mapping. And I'm just taking off the S's and fixing the plurals and singulars Just so that a code is self-explanatory. We shouldn't be calling these countries when we're only getting one, right? So I'm just trying to make sure it's readable. Alright, and then we're just going to see something went wrong in the name of get country. Alright, so let us take this one for a spin so you see the get's really straightforward, right? We didn't want there and we just took the quota with a few modifications. Potentially don't with it. So let's see. So the first thing I wanted to bring your attention to is the documentation. So you see api slash country and idiocy APIs slash country slash ID. So that ID being displayed there is courtesy of our annotation here. Alright? And then if we drill down into its, you'll see that they're actually seeing that the ID parameter is required. No two ways about it. It's a required. Alright? And if we say Try it all to, you can put in that. But I'm going to put, I'm going to use Postman to test this one. All right? So when I say get alright with postman and the same endpoint and CSS and I'm getting the origin now get, which is getting the list. No, when I modify this end point and I say slash one, alright, and then click send, lookout What I get box, so I'm getting only one result. And this is the ID. And it's the list of hotels which there's only one hotel associated with hotel number one. Start with country number one. There's only one hole to what this is on IRI. So if there are more than all of them will be listed under that property or attribute. And then the name is dummy account of short_name is GM. So you see our second Git is working. So let me just put our breakpoint. And surely exactly what is happening when we meet that request. So putting our breakpoint there and then clicking send again, breakpoint is activated. If we look in the parameter listing, we see our value, one coming over. Alright? And then we can go ahead and I'm going to use F ten. So news if it doesn't go into all of the method cause what if I look at a country object coming back, you'll see hotels and that's at least with only one id, the name, the short name, and then we do the mapping. So no result has all of the data that was just in country. And then it's going to return to all k with results is automatically going to deserialize it into serialize it into JSON layouts. Alright, and right there, we're done with our second get. So now we know to get to all, and now we know how to get by baseline apart particular requirements. 21. Setup GET Endpoints For Hotels: Alright guys, so I'm issuing a challenge to you. I want you to pause the video. Yes, it just starts at, but go ahead and pause it. And I want you to go ahead and create a controller for the hotels. You can call its hotel controller. And the functionality that we have just gone through with our country controller. I want you to replicate it in the context of the hotels. So I already have it here. But I want you to pause where wind to go through it together. But I want you to pause activity to yourself. And then we compare notes. Alright, some Buck and I'm Sagan buck because I'm assuming that you pause the video and know you're resuming. And now we can go through it together. So here we have the hotel controller and I went through the same steps. I right-clicked controllers, clicked Add Data Controller, blank API controller called the total controller. I went ahead and injected music under the same services that weren't in the contact controller and initialize them in the constructor? No, everything pretty much is identical. The only things that really changed where my variable names, because obviously I'm not going to call this one countries if we're getting hotel. So get hotels instead of get countries get told tele, instead of get hotel x2 and similarity, you'd want to get to a hotel by ID. Another thing that I would want a point told would be the mapping where mapping to hold the T0. And the final thing would be that I've kind of added more attributes. So as we see that attribute kind of Eden, it indicates the Elis swagger. And I mean, it does dictate the behavior, but swagger does depend on its also to know how LTL formula that documentation. So right here I'm letting her know that this method produces 200. It's also produces 500 because if you recall, when we looked at swagger and he returned to 500, you would have seen something seeing undocumented underneath that 500 error. And so we want to just make sure that swagger contextually tells as much information to the developer as possible at any given time. So and I bring up swagger. You're going to see the segregation country different from hotel. Alright? I hope you're seeing this. And if we look at hotel or any one of these, that the attributes was both attributes were added to. You'd see that the 500 wasn't there initially and see the 200 null 500 wasn't there initially. All right, so that does work or for someone to use Postman to do some testing. So I still have my test from the time. And the thing is with Bozeman, you can always just starts a new tab, right? So instead of using one tub to continuously be changing, I wanted to have one for the ghetto with no parameter and distributes over here. So this is no parameter that see if that works. Alright, sorry, they didn't test my code before. No, I wrote it and I didn't test it and I'm happy to see that it's working. Alright? And then the one with the parameter that also works. And for now that's all there is to setting up our controllers. Alright, so as many controllers as you might have, of course, variations and based on contexts, certain things may differ. But we have a good template upon which we can build our Git operations. Alright, so you can go ahead and just did this off. And then when we come back, we'll be pushing our changes to our repositories. 22. Final Touches and Add Changes to GitHub: Alright guys, so we're back in our project and our task today is simple. Where do swan to check in all our changes? So anything with our SDK would've been modified along the way once again, and anything with a green plus sign was added. So we can just go ahead and go to get changes. And I'm just going to refresh what I don't need to refresh, share all my changes. And instead, someone's put in my message. And my message is just letting everybody know that I added the contour and the hotel get methods also fix the units off work DI dependency injection reference because remember we made that modification in the startup. So I can go ahead and commit all and sink. And once that is done, we're ready to move on to our next module. 23. Securing Your API - Section Overview: Welcome back guys. In this lesson, we'll be doing a quick overview of the concept of security relative to your rest API. Now when we talk about security, even though it is kind of self-explanatory. When we talk about what security is, we kind of have to get into some specifics when discussing hole, we make an API secure. Now some of these things are actually already taken into consideration and come out of the box with at least not.NET Core API. I can't really voyage for other API development frameworks. Once again, voltage API, where they to kind of enforce or strongly encouraged certain security considerations from the get-go from project creation. And then it's up to you if you want to continue with that's really and truly they make it so built-in that you're doing tomorrow realize whole security might be out of the box. So the first and probably most important one would be to use SSL. So SSO is a standard SSL, TLS. There are standards for HTTP communication and what they do is enforce some amount of encryption across all communications going across the pipe, right? So when you are creating the project, I believe there was an option there to enable or disable SSL and well, I didn't bring it much attention to it. But if you want to see if SSL is enabled, you can always right click go to properties replica project, lots of properties go down to debug. And then you would see here that enable SSL is there by default. So even in debug mode, they're encouraging you to use SSL. And of course, when you go ahead and publish, you're encouraged to use AS proper SSL certificates. Otherwise, you also have access to very powerful user authentication system in the form of identity core, which we will be sitting up, which allows you to authorize, authenticate, and let's say sanitizer quests based on who you think should be accessing your API. Now, you don't always need that for an API. Sometimes your API needs be publicly accessible by any and everyone. And then there are some times when somebody's sign-up verify who they are before they can access information based on our API and no, anybody could come an access. The list of hotels are particular hotel act will. There is no restriction to authenticate and authorize a user before we allowed them to do that, however, we will be putting things in place that would allow us to kind of control who gets access to one. Although things like what we expose in our URLs and when we say URLs, I mean like Here we're Remember that when we want it to get to a particular hotel where to load the user topos that ID, that's not sensitive data. However, if it was something like a password or something that, you know, you don't want the world to see, then you definitely don't want to put it into apartments. And so the way you design, you have a defensive way to design your API that such that you are implicitly securing certain things. So with poor design, you could introduce security flaws. So of course, what you allow to be Passover as pretty and takes Laura's parameters. What you hush Are you encrypt along the way all of those things, it, in making your application secure. Now with all that said, sometimes we think that we need to have a very, very secure thing out. We tried to put every form of security into our API, and that's not necessarily true, as I've always said, context determines a lot. So I'll give you an example of one time I had to develop an API or upper are owned a third party. And the concept was that this third-party service provided some messaging services that my company would've used for various applications? No. What we didn't want to do was integrated the third party endpoint into 5-6 different obligations. Because if the vendor changed their design or something, they would have five or six different touch points that would have to maintain. Instead. I was put in charge of developing an API that would consume the third party API, and then the internal applications would consume my API so that if the third party changed their design, we would only have the 1 to change because everybody's consuming our already internal API. Know when, when, when the company mentioned that, of course, security was very high on the list. And I went ahead and implemented all sorts of authentication on Tolkien's. And we'll be looking at Tolkien's also as we go along. But all sorts of security protocols and really and truly was overkill because the internal API was just that it was internal. We had IP whitelisting and very strong network protection protocols surrounding what was operating internally on our network. So to have an internal application need to verify who it is in order to access the another internal API before it goes out to the third party. All of that was really overkill. It's giving us scenario off where I personally, I would have implemented something that was overkill. After awhile, we just built all of the excess stuff and we had all the security protocols to fend off balance at all. So once again, context determines a lot. However, for this section we will be implementing authentication, meaning our clients will need to register with our application, with our API application. And they would have to login passing the username and password that they would have used to register. And then subsequent to that, we will be assuming them what we call JSON. Web tokens are bearer tokens which will have information that will inform us each time they make a request of who they are so they don't have to keep on logging in before they can do things that do that one time, get this Tolkien and pass that token along each time for us to verify and accept or deny. So that is what we'll be doing in this section enough of my monologue. Next stop, we're going to be creating our identity core are integrating identity core into our project. 24. Setup User Identity Core: Hey guys, welcome back. So our first line of security will be for authentication. And to implement the authentication features in our API, we're going to be taking advantage of the built-in libraries of neck CT. So we're going to be making a few modifications to our database context, our startup and other little things here and there. So let's start off with our database contexts where we have to change it from being DB context to null being identity DB context. So this is just another class that allows us to take advantage of that entity services. And when I do control dots, you see here that you have the option to install a identity if R into different work core. So you just go ahead and find and install the latest version. And then once that is done, we need to make one more modification. Tour on model creating, where I need to say BCE dot on model creating. Alright, so after calling the same function in the base class, which is our new base class, I will just pass along the seam builder objects that we're using in the current DB context. Now that's step one done. We'll go over to the startup file and then start making modifications here. Now what we need to do is configure our identity services to know which class is going to be used to infer the tables that will be generated. So before I move on, let me just backtrack a bit and explain what's going to happen. Where telling our application from the get-go that we want to use owe us identity services. That's what we're about to do. Know the identity services will be based on a database connection to well, a connection to a database that has tables to facilitate identity related things, uses storage roles, storage claims are known both things. So what we need to do is configure identity services to know which class is going to inform how the users table should look. And if potentially there is another one for roles, holder rules, we'll look, et cetera. So already built-in is user called our class called Identity user. Alright, let me just go ahead and include, say see it's legitimate glass that's already built in, that can be used. We look at the details of identity user. You'd see that it has fields for local and you don't have to come here. But if you want to get to that point again, this control click and then continents or control click until we get to that part. Alright? So we have these default fields that will come up in the database as you can see of ID, username, email and password, password hash, right? So those are common fields that any user table needs to have its dealing with the hashing automatically. It's all, it's always going to have all of that built in. No problem. However, there may be times when we need a bit more inflammation from our users then just email, password and username potentially. So they allow us to extend the identity user class and put in other fields like we made the necessary. So I've already kinda started that process in data creates this grass API user. You can go ahead, right-click your folder, go to add new class API user. And then in API user, what I've done is inherit from identity user. So remember once inheritance happens, we did that with our details earlier. So we're doing it no, with admins, it's user, it's going to automatically inherit all of these fields as well as any other field that I see I need. So in this case I just need firstName, lastName. You could want dates of birth equal to one country of birth, area code, other things, whatever it is you want, you can just extend this grass and add them, but it will always have these fields by default. So once you have that class created, you can make two changes. Before we go back to start off, I wanted to add that class as a context for the DB context, my angle brackets and seeing DB context year relative to API usable because by default it's good to use identity user. So if you don't have that requirement where you need more fields, then you don't have to take that extra step. However, it would be good to do that extra step because later on if you need to extend it, you can do so without much headache or hustled. Alright, so that's one more change that we may enjoy. Db context. No, we need to configure the identity services. So I could do that from here, but I'm going to kind of bring along another journey no, where we don't want to some sometimes you don't want to keep on putting in and putting in and the start of the stacks is swell. And then you have to scroll through mountains of quotes, a fan one configuration. So what we're going to do is go over to our project to create a new class. If you wanted to put it in a folder, that's fine, but I'll just leave it at this level. So I want to call it service extensions. And then inside of service extensions, I'm going to have public static void. And I'm going to call this one configure identities. So this class is going to be like, well it is the service extension, say they'll configuration that would go on to burden in this startup file width, we can abstract it to this and it's called the method's apart ME, well, you'll see that. So I'm going to say this as a parameter, this, and then I service collection and call it its services. Include any missing references. There was a goal and then this is not willing to say that I need to have this as a static. Gus, There we go. All right. So inside of this method, I'm going to have a verb, I'm going to call it builder. So basically builders, there's going to be like amalgamation of us building of the same services that we would have added here. So the same way you would have said Services dots and you add this and that. We can abstract that over to this glass. And now we just call it, it's on the other side, so you will see in due time. So we're going to be i being r dot add identity core. And then we're passing in the user class. So once again we're using the custom user class API user, API, user, right? And then open and close brace. And I just need to include any missing or reference their goal. And then I'm going to have my lambda Tolkien where can customize certain things about holy tongue goes, the user interactions, I can set my password policies writer. I can see that all bussers most required digits or have a minimum length, use unique characters. All of those things are right there, altough the walks. However, I'm more interested in just making sure that my users, so q-dot user and require unique email is true. Alright, that's the one to one. I'm really interested in enforcing retinal. However you can experiment and you can add the others that you feel are necessary. So that is the first line and then I'm going to say builder is equal to new identity. So most services will come with like special builder, GAS at Aunts, all of that. So I'm just going to say density builder and include the missing reference. There we go. So new identity builder, Give me the builder, right, so that's the object that we just started, that user type. Alright, so whatever type was specified, What's was busing in there, and then type off because I want to use rolls. So the same way that there's a built-in identity user, there's a built in identity role. So Roland means are you admin, are you user, whatever it is, that's what the role means, right? And then after specifying that row should be there, then I'm passed into i collection services. Object in the form of services. After all of that, I'm not going to say builder dots. And we need to tell it where it should be storing are which needs are basic needs to interrupt with for the Identity Services to husband. So I'm going to say the base context, right? So the DB context that we're using as our database, we're passing in the matching object for that. And one more land to default token providers. I did say we will be using Tolkien's book later on with official the Tolkien bits. I'm just putting all of that there. So just for context, once again, this builder object is really just saying, I'm building up the everything that needs to do top to add to the services. That's pretty much what we've been doing all this time. So here we said Services, dots, and we add all of these lines and options ongoing don't seem thing would a core policy and so on. So now that we've extract, extracted all of these lines. So this method or to discuss and this method I can know in startup see Services dot on authentication because that's the first thing I need to add, authentication. Alright, there's authentication on core also, but I'm using at authentication of them had any problems with that one so far, so I'll just stay with it. And then I'll say services, configure identity. Alright, nice and simple. So services not configure identity is basically what we just did here. So you can start looking at it this way anytime we have to add in something to the startup, if it's not the one liner like this, maybe we can start with akin to extract these things to that file and have the builders to send over the object whenever it is called. Alright, it's not the end of the world, but different people like to see different things. So some people, myself included, who don't like to see bloated starts off files. And at least when you have that much code, you have to be scrolling through enemy a scroll past the configuration on five times and 40 realize was there. Those are the things can get annoying when your, your application on grows. So I'm just showing you a way that you can obstruct too many lines of code from your configuration section and have it in a very confined space. So now we've done all of that, and we've done all of that setup. What we want to do is do a migration nowhere with ADD the tables for the identity, sir. So what we'll do is say dash migration. We know this part, say added user are added identity. It just puts it that way it added identity. And once we do that, we get to our migration file. So now when you look through, you see the different table names we have the ISBN intervals table, we have is peanut users table. And if you look very closely, you see that in addition to all the default fields that we saw earlier, we also have the custom ones that were added to the gas. Alright, firstName, lastName. So it's going to scuffle and is still going to put in our custom fields. Alright, just the same way over and the rules. And if we wanted more information on rows done this, we could have added a custom class, extended its, and it would have been the same. So let's us go ahead and update our needs obese. And with all of that done, we have finished our configuration for our identity services. So you can give yourself a pat on the back. However, most of what we've done is in the background. If you on tangible evidence of something being done, you can always check your database and you'll see the tables that have been generated accordingly. Alright, but our next step is to actually setup the endpoints such that the users can possible inflammation and get registered as users of our API and also for them to login. And then after that, we'll talk about how we continue to verify that this user should have access after they have loved him. 25. User Registration Endpoint: Because welcome back. So we're going to continue our journey into setting up our authentication for our API. And we'll be setting up this endpoint for user wander, a distribution and to login and by extension authentication. No, I've already kind of cheated and gone ahead and set up the new controller so you can pause and go ahead and gets up to speed, right? Could controllers but creates up brand new controller that's blank and call it a cons controller. And I already went ahead and kind of started doing my injections. So 2-year familiar with to you would be seeing for the very first time. So you already know the logger and the mapper, so I don't need to explain those in any great detail. However, you would be seeing user manager and sign in manager potentially for the first time. These are two built-in libraries courtesy of identity core. So when you type them, you may want to include the missing reference and you'll see those start to appear up top. Now notice the context for the user manager and for the sign-in manager is API user are whatever the custom user class is that you would have used when you were setting up identity. If you didn't use one, then you continue to use identity uses. So whatever class it is that you sit as your context in your configuration, and that configuration file would be here. Whatever class you sit there, you continue to use that throat application. Alright? So user manager gives us access to a bunch, our suite of functions that allows us to manage, sign-in, retrieve user inflammation, I'd users. So we don't want to have to write any custom code to be adding or I don't have to go and put in any unit of work functions for user, User table interaction are relatively interaction. All of those things come out of the box with the use of money, just sign in manager and you have another one called Rules manager. If we need to use it, then we will. But I'm just the teen or most of those things are encapsulated in these services which can easily be injected into our application. So now that we have setup our controller and injected all of what we need, we need to start writing our endpoints are first, endpoint is going to be for registration. So it's going to look something like this. Public async, task, action and result. And the name is register. For registration, since we will be requiring potentially sensitive data, will not potentially will be requiring username, password, and so on. I don't want to send that across the pipe in the parameter. So we discussed that in the overview video where I will see you in that. Using the parameter is quite fine when it's something like this, just an ID and nothing to damming, right? But then when you get to asking the user to register and submit sensitive information, you don't want to just start seeing string emails, string password, et cetera. Because then everything would actually come across in plain text over to the endpoint. So what we'll want to do is make this one a post. So we, we have done work with the GET verb. We haven't done much work or any work with the post. So a post, just like when you're submitting a form on the internet, when you click Submit to go to, let's say sign up for Facebook or sign up for something online. If you look in the URL up top, you don't see any of the information being listed out. You just know that your information left one page and supposedly went somewhere and delta pH could represent it's, that's what the post operation is. Alright, so the message is encapsulated and kind of hidden from prying eyes. When we do I get it is sent across four implant site, just like what we saw here. So there's no reason tie it. So ofcourse when India with sensitive information, you don't want to use a guitar, anything that will not tied the inflammation that's being sent across. So with that considered, the parameter that we're going to use here is going to be a cost on one. So I'm going to put in an annotation to say get the information from body. So the sender needs to send it in the body as opposed to in the URL and the body of the request. And then we can specify a data type that should take the information. So I'm going to say user detailed sovereign creates a user detail as yet, but I'm just going to say user detail. Alright. So let us go ahead and creates this user dto. And then I'd explain why it can't work like that. So in models we click Add class. We're calling user need TO. And then user detail needs to have at minimum the same fields that we need to go back to our EPA user. And two, we need the user to provide. So this is how I am designing my user details. They can pause, replicate it, but I'm going to walk you through it's anyway, so firstName, lastName when registering. Yeah, the option to pass those two fields over. Notice I said option because I'm sitting neither as required. We have the phone number. So if you want against industry or phone number when area, just saying for the API, once again, not required. However, email is definitely required and password is definitely required. And then for email will actually be using this as the username also. So if we have this detail, as usual, we have to make sure that our mapper knows about the dto. So mapper initializer, I'm just going to go ahead and see that APA user. And user dto needs to know about each other and reverse map, alright? And so that is what we will do. So the purpose of the from body here is to see that when, when I request hits this endpoint, you will look in the body of the request, don't look in the URL. So one, I'm not requiring anythi