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

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 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

    • 1.

      Introduction

      3:49

    • 2.

      Install Visual Studio 2019 Community Edition and .Net 5 SDK

      6:46

    • 3.

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

      2:16

    • 4.

      Setup GitHub Account

      2:28

    • 5.

      Install and Explore PostMan

      9:39

    • 6.

      Create and Tour Web API Project

      7:55

    • 7.

      UPDATE - Upgrade to .NET 6

      3:12

    • 8.

      Configure Logging using SeriLog

      14:17

    • 9.

      Explore Swagger UI

      10:48

    • 10.

      CORS Configuration

      6:40

    • 11.

      Review and Add Changes to GitHub

      4:39

    • 12.

      Implement Data Classes and Entity Framework

      26:12

    • 13.

      Seed Data In Tables

      8:10

    • 14.

      Setup Service Repositories and Dependency Injection

      31:30

    • 15.

      UPDATE - Strongly Type Includes for Unit Of Work

      6:08

    • 16.

      Setup AutoMapper and DTOs

      21:20

    • 17.

      Review and Add Changes to GitHub

      3:28

    • 18.

      Overview - Setting Up GET Endpoints

      4:49

    • 19.

      Construct GET Endpoint

      26:42

    • 20.

      Construct GET By Id Endpoint

      9:33

    • 21.

      Setup GET Endpoints For Hotels

      4:03

    • 22.

      Final Touches and Add Changes to GitHub

      0:48

    • 23.

      Securing Your API - Section Overview

      6:52

    • 24.

      Setup User Identity Core

      13:39

    • 25.

      User Registration Endpoint

      30:19

    • 26.

      IMPORTANT - User Registration Endpoint Fix

      0:56

    • 27.

      Add User Roles

      10:37

    • 28.

      Explore JSON Web Tokens (JWT)

      5:10

    • 29.

      Implement JWT Authentication

      31:39

    • 30.

      Protecting Endpoints

      8:11

    • 31.

      Review and Add Changes to GitHub

      0:22

    • 32.

      Construct POST Endpoint

      13:35

    • 33.

      Construct PUT Endpoint

      23:38

    • 34.

      Construct DELETE Endpoint

      7:24

    • 35.

      Review and Add Changes to GitHub

      0:44

    • 36.

      Value Added Functions - Section Overview

      1:16

    • 37.

      Implement Paging

      17:51

    • 38.

      Global Error Handling

      11:25

    • 39.

      Implementing API Versioning

      12:38

    • 40.

      Implementing Caching

      13:49

    • 41.

      Rate Limiting and Throttling

      7:15

    • 42.

      Review and Add Changes to GitHub

      3:24

    • 43.

      Architecture Changes - Section Overview

      2:17

    • 44.

      Setup Data Models Project

      7:24

    • 45.

      Setup Application Core Project

      10:50

    • 46.

      Clean up and Test

      15:25

    • 47.

      Review Modifications and Benefits

      15:00

    • 48.

      Configure Hosting Environment - IIS and SQL Server

      6:39

    • 49.

      Publish Application to IIS and SQL Server

      24:58

    • 50.

      Create Microsoft Azure Account

      7:12

    • 51.

      Deploy Application and Database to Microsoft Azure

      17:27

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

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.

296

Students

--

Project

About This Class

Overview

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

Teacher
Level: All Levels

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

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.

Transcripts

1. Introduction: Hey guys, I wanted to take this time to welcome you to this new course, ultimate ASP.net 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 ASP.net 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 using.net 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 ASP.net 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 and.net 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 microsoft.com 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 ASP.net 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 ASP.net 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 all.net 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 is.net 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 the.net 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 the.net 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 ASP.net 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 R.net 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 Microsoft.com 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 ASP.net 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 GitHub.com. Does GIT HUB DOT COM, github.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 man.com. Postman does light Luca who delivers your mail, Horstmann.com. 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 api.com. 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 api.com, right again to stop that's in free for api.com. 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 ASP.net 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 the.net 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 ASP.net 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 a.net 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 chose.net 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 of.net 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 Microsoft.net 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 your.net 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 4.54.11.5, 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 for.net 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 for.net 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 package.net 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 anything in the URL. And two, if the user passes anything in the URL, I don't care. I'm not looking for any inflammation in the URL. However, the body of the request should contain information with fields that much to the user dto. So they send more information than I need. It's will be ignored. But at minimum, they must send these to for me to process it. So that's so everything kind of ties in when we talk about sanitizing the requests and making decisions based on what is coming across the pipe. Alright, so let us go back to our cones controller. And then what we want to do at this point, and we can do a number of things. So I'm going to firstly, trend loved NC registration attempt came in for and I copied on Piazza, that's kind of brimmed myself. But let's say registration attempt for user dto, dot email. Alright, so whatever email came in over the user dto, that's what I'm putting there. So I'm going to also check if the valid state, if it isn't a valid state. So I can see if models. So this is all we verify forms, right? If you do, if you have done MVC and dizzy or just learning API, it's pretty much the same process. We're looking to see if models state is valid, right? So at this point I would probably say if it is not valid, then I went to return a bad request. So that means you sent over a request to register, but your validation field, so you didn't include the email they didn't include or you didn't meet whatever standards I would've laid out for you regarding the data you should've sent, right? And then I can return the model state so that it will kind of inform the sender what went wrong. Alright, so if models state is not valid, then we do that. Otherwise, we can proceed to try. Just try top, top, catch that exception. So let me just deal with the exception. Parts of it where I'm going to see log arrow, something went wrong in that register section. And then in previous times, what did we do? We returned with a status code 500. So another type of return that you can do when there was a problem is literally return problem. And you put in the same kind of message. So I could put in something went wrong. All right. And then tell it that it has a status score of 500. So I'm just showing you that there are different ways, you know, if you are looking at other resources, you may see me do it this way and somebody else returning our problem, somebody is returning the status code manually. There are different ways to do this, alright? But then for the ones that are built-in and they already gave it a method's I've generally I encourage you to just use those. So we've taken care off the bad situations. I'd like to just say if it is not right, do this. No, what do I do when it is right? One, I can say var user is equal to mapper dot mop into API user. And then I am mapping user detail. So then it will say, okay, much all the fields which we know already. We know how the mapper works by a null. And then know that I have the user. I can say var results is equal to. And I went to our weight, our call to my user manager dots. And then here's, here's a bunch of functions. Like I said, we can do a number of things. I can say create a scene. So user manager creates a sink, and then I'll just pass in the user objects. Alright, so go ahead and create that user. It will automatically take it to the password, hash it, store it, do everything it needs to do. We didn't have to write any complex logic to really facilitate that, right? But then sometimes things fail. So I'm going to say, if not result, not succeeded, right? So it will tell you, did it succeed are not, then I'm going to also return a bad request. So I'm going to say something went wrong. This time. It's not the models, the thing. It's probably just an arrow. So the thing is that the result object actually gives you the arrows. If you really need to list them all to, you can probably put them in a loop, list them, put them in one string and return them if you want, if you want to give the user that much detail. But sometimes those details can be too sensitive, so you have to be careful what information you're sending Bach tool, the calling clients, right? So at this point, I'm just going to save battery requests. It was a 400. And it is because the user or distribution on field, that's all you need to know. So try again later because this could have been my fault. Otherwise, if you will, as something serious would have given them a 500s and all. It is on our side that the problem is, and if it is that you send incorrect data, then I'm telling you what is incorrect because a motto states will list that shouts. Alright, and that's pretty much it for the register. Now since we've done the register, I think we might as well just do the login because though no real way to test our register statistical login. So I'm actually just going to copy and paste this code right below. But what we need to do is change the action name. So this is a login action. We're using the same user need TO were taken from the same URL, from the same body, sorry, ignoring anything coming in the URL. And then what we're going to do is say login attempt for this user. If it is invalid, once again, validation constraints, email, password. No. One thing that we may want to consider is, do we need the same dto or should we use the CMB TO for login and register? Same principle with the other details, right? Because for a login I don't need your firstName, lastName, phone number. I only want your email and password. So what I'll do here is quickly just do class to say login ETO. And I went to take these two fields, put in just the login because it's absolutely necessary Far login stuff. But then I let this inherit from logins. So the fields are shared across the board regardless. Alright, so I shouldn't call it a login user. There we go. Let my mapper know that it is a wave and the mapper, No, I really don't need to let the mapper knowable this one because the operation is going to be slightly different. So I'll leave user detail in the Mapper, but I won't put this one and I'll explain why. So login user detail. So once again, this is another parts of security when we sanitize exactly what we want. Because if the user may have included malicious, sorry, the client aren't yell at the user sending the request. The client sending the requests could have included malicious inflammation in the body of the request. By doing this part here, I am saying that I am only looking for fields that match what I have all aligned in this dto, say this AND more information than I need. It's going to be ignored regardless. So that's another part of the security considerations when creating APIs. So we get the login user dto. And then for the login, okay, well, we validate it. Okay, good. So we check the models state and then what I'm going to try. So nothing much else to change here except maybe the log messages as to make sure that we are accurately representing where watched Twin wrongly. Alright, so under the trie, what we're going to do, I don't need to do any mapping, so let me just remove what's in try and start from scratch. I am going to say var result is equal to, and this is where we use the sign-in manager dot passwords signing a sink. So you see that and you can even do a check. You can check to see if the password would be carted the bursts Australopithecine and ofcourse that'll say held the situation at this point. Because we want to actually signing, right? So sign-in is seeing takes two overloads. We can pass in the whole user object. I just took all the mapping and the password. Or we can choose to just put in the username and password, which is the one I'm going to use. So you see I'm both options. So if we kept them upping will pass in the whole user object as well as the password. In this case, that's wiki though. So I'll just say user dto dot, and we're using the email address as a username and user dto dot password. And then is for assistance. So let's read what is persistence is. It says flag indicating whether the signing cookie should persist after the browser's close. No. I this is an API. I don't know what kind of application is calling. The API could be postman. It could be the browser, it could be a mobile APP. I don't need to persist anything, so I'm going to say false. Alright, and then the last one, Lacan failure, I don't want to lock anybody when they fail to login would be too much of an administrative overhead. Once again, context is everything, but this is what our sign-in code loops light, nor the result is going to be a similar object to the register attempt. So we can just say if results are sorry, if not, result not successful or sorry, this is asynchronous. So when we fail to put on the await, then the result that we're going to get these off type tasks, not off the type that we're expecting. So let me make sure I put on Dewitt. And then when I do that, you will see that the intellisense giving me what I would expect. So if it is not successful, let me just double-check what we did when it wasn't successful here. Then we say, we say bad request on top. But if it's unsuccessful, login attempt, it's not necessarily a bad response was I would just say are bad request or the hotel would say is unauthorized. Right. Which is a for 01 if I'm not mistaken, right, unauthorized. And I can probably just return the user detail to see this is what they attempted to use. It's unauthorized, I'm sorry. Alright. Otherwise, if it gets this fire, that means everything is OK. So we'll just return. I could return. Okay. I've used accepted in the past, right. So anything with a 200 in the 200 range would be seen as an okay. Response. So OK. As 200 you have created which is I think tool for yeah, I've accepted which is thought to et cetera. You don't have to worry about memorizing these codes necessarily. Does know that in particular situations you want to use this one or not dealt. Alright? So then that is what our login function will look like. And okay, I've made a change. This no art. So let us all, the register is seeing that not all quote paths, return of o. That is why I am so sorry I missed this one node. So remember that you always have to have a fan other returns. So the same way that we said that you stay in Windows, this what will return accepted afterwards, after do that here. So I put return accepted up top here also, right? I have accepted your registration attempt and then that is done. No. Before we move on to testing, I wanted to bring something very important to your attention and that is the routine considerations for this endpoint where it established that the rule would be api slash controller, in this case, API slash cones. In previous times that say the hotel controller, we would have determined that we can't have two identical get operations. The name of the action is irrelevant, but I can't have two operations. How being identical verbs, the verb can be the same, but then there must be some nuance to one implementation of the verb from the other. In this situation, I have both as post. Both of them are post. Once again, the name here doesn't matter what they are both posts too, which means that if I attempt to do any post operation is going to not know which one to use. They're both kind of identical in terms of what they're expecting. The only way I can really differentiate between these two is to give them their own roots, right? So I can say the root for register is register. Alright? And then the road for a login is login. So that we, at this point, the only way to hit register is to say server slash api slash slash register. As a post request. Though we do hit login is to see whatever slash api slash o colon slash login. So I'm specifying that a route for this endpoint is login and this one is register. Now we, they can have identical verbs, but because there are different locations, they won't interfere with each other. Alright, so this was, that's trying to register a user real quick. So what do we check old, what swagger has generated for us doesn't append anything to its call for ID here and I need there. They are. No post, not get, right. And then if I expand, they will show me what the object needs. The look like our Chan looked like when it is coming across the pipe. Alright, just for those same for login. So you see the difference. Remember that we have two different details. This one has email password and the custom fields. This one. It takes email and password. So that's what I was saying, that when in a situation when you don't need all the information you create, I need to yield to limit exactly what you need in that situation. Alright, so let us try with the registration attempt. So I'm going to leave that that email. I'm going to put in some bus word that has characters and a number. And I went to leave everything is blank because all I really need our email and password, however, by leaving these as they are, they are literally going to go over as String, String and phone number. So let's see what happens when we click Execute. It's, this attempt is giving me a 500 error. So this would have been one of those exemptions caught on it saying cannot resolve a particular service for the sign-in monitor. Alright? Alright, so the sign-in manager is giving up problem and I would like to go in and troubleshooting. But when I'm thinking about is I really don't need the sign-in manager for this API. And I'm going to explain. So when I put in san in manager and injected it and all of these things, it was because that's like a knee-jerk reaction. Whenever we have authentication to do, we want all the libraries that can help with authentication. Alright? However, in the case of a web application where somebody would submits a login attempts through a form, click Submit, and then be told they are allowed in through some message or some indication that says hello username. That is really the San in manager creating something like a session or a cookie based on the configuration setup for managing that user session. In terms of an API, we're not willing to be maintaining a session for new user. Yes, your register, what? We don't know when you're going to be calling the API whole lung. And it's not like you're going to be a lingering inside the API for 1R few cause the eBay's going to accept your request, give your response on be finished. That is why we are using Tolkien's. So I don't want to get too, once I hit off myself and start discussing Tolkien's. But because of the Tolkien's, we really don't need the sign-in manager in the traditional sense of what the Sign In manager does. So I'm going to remove all references to the Sign In manager really. And I'm going to comment out the login endpoint for no. So that's control, casey, Just a comment. Alright, so I really don't need all of this just so we'll get there. But I've just got to head off myself and I apologize sometimes these things happen. But hey, we're just going to comment out the code and then we will revisit it later on. Know as it relates to some of the error messages that we want to send a Bock. What I'm going to do here is kind of I had all the result arrow side. You'd see you could find a way to put the results arrows in a package and send off someone to say for each error in results, errors. I didn't say it couldn't be sensitive information. So I'm accepting that risk. But I'm going to say model states dot and I can say add modal arrow, which is then going to ask me for our key. I don't have to put in the key. And then I'm going to see error. Dots, I'm sorry, error being the message coming back from the result attempt code. So here's what I do. I put the code as the key, right? And so the key there either means what's the name of the arrow. And then the core description would be right there. Right? Then we can see bad request user attempt failed or they'll sit the model state because it's already obvious that it failed. So that's how we will proceed with the error messages for our registration at him. So lets us try this one more time. Alright, so wear buckskin swagger with all the login and points. But we're going to just try putting in my complicated password once again and then executes. Alright, and this looks a bit better. Alright, so first there were not getting any complaints about any user manager or an IT service not being registered. That's 12. See here now we're getting back a 400 and we're getting back some details as the watch is wrong. So in valid user name, username, blank, blank is invalid and can only contain letters or digits. Alright, so that is because we did a mapping, but we're only asking for email. The actual identity user has to have a username value also. So what I need to do here is to specify the user dots username is equal to the email address, so email address is required field. Username is a required field and password. They're all required fields by the identity user. So I was going to providing email and password. I'm just going to go ahead and provide the username. Also, what is the same as the email address? All right, so let's just try that one more time. All right, and when I do that, and I put in the same details user at the example and password one, look out while we get, we get a 200 response. All right. And was just stunning us. Everything's good to go. So it has not failed. There's no validation error or anything like that. I notice that it says on documented for the tool to glucose, we didn't let the controller nor let swagger know that tool to is a potential return type. So remember that we did that with the other controllers where we listed all the potential return types. So you can go ahead and replicate that in the UK home controller, what foreign always Singapore, a distribution on process. You know, you might be disappointed. They are not getting to test the login one just yet, but it's really not a login. It's more it's going to be more like an often d, an authorization to see, okay, you about Tolkien and it's valid, yes, you can access the resource you want. Because once again, a login really is to create a session and allow somebody access for a period. Whereas what I took with an API, we don't know what period you may need access for. We don't need to facilitating for a longer period than it takes to process your request and give you your response. So we just want to know that you are unacceptable, accessor, validate that, give you what you want and then we're done with you. So that is why we will be doing the toolkits. So when we get there, we will go ahead and hosho more hallway restrict access. 26. IMPORTANT - User Registration Endpoint Fix: Hey guys, one quick addendum to what was done in the previous activity, sitting over a distribution endpoints and everything it worked. However, when I realized that my user did not have a password and that's because I did not put this pipe on. So if you look at the creates user function, it has two overloads. One where it just creates the user and another one where it asks you for the user and the pastor to go with them. So I'm not entirely sure why they feel the need to meet two, because for me a user has to have a parser bots, I guess for different situations, it may need to store something or not the others. So user comma and then from the user need teal, we take the password so that we can ensure that when the user manager creates that user, that password is also going to get hashed and stored on their record. 27. Add User Roles: Hey guys, welcome back. So one very important parts of user authorizes Sean is knowing what role this user is in a pontoon. No, we haven't done anything associated with roles, were more preoccupied with getting the user information, validating it's and whether we create the user are not. Now when it comes to roles, the roles that are allowed to exist in the system prior to the system being used. So the same way that we would have set up these seeding operations for hotels on countries thereof, less importance really than roles would be so on to make sure that the rural side there from the get-go so that when the users start registering, the rules are already there. So what we want to do is see them, but instead I'll seeding them the way that we see that country and hotel. I'm going to show you a way that we can abstract that operation from o dB contexts and keep the DB contexts as light as possible, similar to Hollywood has shown you to do that with our services that we are installing. So what I'm going to do is setup a new folder, have configurations are at m. Just going to go ahead and add another folder inside that and I'm going to call it it's entities. So configurations for anything that's his entity related. And then I'm going to add a class. And then I wanted to call this class role configuration. Go ahead and add it. And then this rule configuration classes inheriting from I entity type configuration. And it will be of the type, then THE role. All right, let's go ahead and include any missing references. So it doesn't hitting rural configuration or that it's been to be associated with that configuration type. And of course we have to go ahead and implement whatever this is seeing needs to be implemented, which is our configure function. All right, so there's also once you've gotta go into possible or the seam builder that is in use on modeling creating. So then we can actually replicate the code that we have where we say builder dot has data. And then instead of Builder dot has data, we can go ahead and create new roles, neural objects. So let me just select all these quotation marks. Alright, so new identity rule. And we're just going to initialize this object. I'm not going to give it an ID, startled zone id, the name that's called this one user. And we have to give its unnormalized name, which is really just capitalized version of that. Off the name really. And then. I'm also going to give it admin administrator, that's built administrator. And then the normalized is all CHEOPS, version of ministry, door, add ministry. It's always mesure the spins rights of spent nice debugging but spellings, so don't be led me. Alright. So not that we have this configure method and as many rows as you think you may need, you can go ahead and configure them. But the most important parts of all of that is when we're ready to put it into the system, we need only say builder, dots, apply. Sorry, build dir dot, fly configuration. And then I'm just going to say a new role configuration. And then include the missing refrence store knew Lee created. And there we go. So you see that looks much to me, that looks much neater than having all of this. Remember that the reason we moved it from the top here above the list was that it was so huge a function because a follow these lines. If you want, you can pause, right know, and attempt to build other configuration files for country and hotel. Alright, so I hope you actually attempted it because I did it. All right. So I'm not going to ask you to do anything. I'm not going to do. So just in case you need some guidance. We went ahead and created configuration files per type. Alright, so we have Holton, I'm OF country and wherever all So we created, rolled together. I did country, same naming basically could copy and paste code and assumes essential parts contra configuration that I entity type configuration relative to country, the context. And then the same code that was there to create the countries I just cut and paste. Alright, the only thing is that in the previous one we had builder dot into t, something like that and I removed that entity part. So he says build their dots has data so you can go ahead and replicate that across both country and hotel. And if you're doing your own thing across any other one and no, you're on model-building. Looks much cleaner. Alright. And I think I'll just put this one. I don't really didn't get much as where in terms of the order boats out of us puts it at the bottom. And since that's the order in which everything was being created anyway, so country, then hotel, then we have the rules. Once again, these two are really optional in terms of what's really needed to get an application up and running, right? So now that we have the role configuration are seeding, we can just add migration and say added default rules. And, and resulting migration file has two entries into our rules file. So you see generated its own ID. That's why I didn't want to modify that. But then we get user and we get the administrator. So when we do update database, it will go ahead and do the insert. So once that is done, we have two other changes to make. So one is in the user detail. I've introduced this collection of type string and I'm calling its roles, right? So we're giving the user the opportunity to say which role or roles should this person have, right? And then in the cone controller, right after we have vetted if the registration attempt was successful or not, are the user creation operation was successful or not. Remember if it gets beyond that is statement, it means that it was successful. Then we did the extra step of saying user manager dot, dot, add roles async. And we're adding to the user that was just created, the role that came in, our roles that came in. So if you look at this, it has a few overrides. One over ad allows it to or not overlap overload, sorry. So the one overlord allows you to just pass in a list of roles. And that's it. We'll just play it and add to this user. So once are all exists, then it will be associated with the user in the backend. Once again, built-in function, not much code or effort needed on our parts. Let's us take this for our speed. So in swagger, you see that they're modifying the potential values, right? So that they are showing it. I can pass in an array called rules. So the irony is the square brackets, whereas an object is the curly brace, right? So let's try it out. And I'm going to leave this same user doesn't seem use it out. We've got success with last time. All right, so that means I should get some validation message to see it shouldn't work what I'm going to pass in the role of user and when to execute. And then here's what I'm getting. So the result is that I have a 400 bad request. Duplicate email is the issue. It's already taken so that validation is working. So let's see. User at hotels. Hotel listing.com does something different. And that's the user. So I'll go ahead and execute. And what I'm getting is not a bad response. All right, that looks good. So let's see what happened in the database after those operations. So I'm going to kill the execution, go into the Server Manager. And Firstly, I want to look in the users table session of at least two uses based on my tests so far. And there we go. We have USA, total listing and user at example. Alright, so that's good. The next one would be the roles. So I just scaffolded the rules myself. I just see then the rule is in. So these are the rules that we've created. However, the user role association is stored here because it's a many-to-many. So they're seeing that many users might have many roles, right? So that's why we load an aria, because maybe one user might be administrator and user, maybe an supervisor, et cetera, et cetera, based on a system. It's all contexts, right? However, in this table, when we view data, then we should see the user ID associated with the role ID. Alright, so if we were to just go back and double-check, you see that this is the user ID. There we go. And the eight, f, seven. So if I look at that same user ID and being it if seven and the role 755. So you have to go to this one to see which one is 755, which is user. So that's, it's all we start integrating rules-based authorization into our systems and all our users. When they get registered, we'll get registered with their appropriate roles. 28. Explore JSON Web Tokens (JWT): Hey guys, welcome back. So Randall, We want to start discussing our JSON web tokens, but before we go ahead and implement them and are at mountains of beautiful code. To do that, I want to sell a full understanding of the purpose that they serve in the whole workflow, the API security and everything. So there is a leading authority, at least in my book, they're leading authority in the form of auth 0. If I'm not mistaken, there probably pioneers for this kind of protocol. But you can go to JWT dot IO and you land on the CMP is that I have here where they display to you some put Tolkien and kind of show you the breakdown. So we are going to discuss exactly why Tolkien's are unnecessary and what exactly they tell basically when, when they're being decoded. So let us see. Once again, the person attempts to login to our API, or they attempt to access our resource from our API. We have restricted access. So we are telling them that we need to know who you are and what you are able to do. But then I need to make sure that you are somebody who should be able to access my system to begin with, right? So our Tolkien here pretty much would be issued to them after a successful login attempts. So they would pass over their username and password that we already have stored in our system because they're registered. Once we verify that they are, who they say they are, we're going to give them a token with information that we have on them so that when they are making subsequent requests, they can use this token instead of trying to login every single time. So this Tolkien would represent a hush are some encoded representation of all the information that we have for them that that could include their username, their password, their password, apologist, mcdr, their username, their e-mail address, if they are different. Whole long we're allowing them to use this token to access the system, what role they have. And this other one called claims, which means that you are able to do this whatnot that starts on vibrate. So those are the things that we encode in this huge string and send back to them after they have successfully logged in. Or the benefits of this is that on their side, they don't have to keep on calling the login because remember that we're not keeping decision to know if they were logged in previously or not. So instead of them having to try and login every single time they're going to make an API call. The login ones get this token and then make it rather call with this token attached to their requests. On all aside, when we get the request, then we see that there is a Tolkien, we decode it, validates that it came from us and then redirect them accordingly or provide the response accordingly. So that is what JWT security is all a boat. And you will see that this string is actually color-coded red. I think that's going to say love vendor and blew, right? And pretty much eat six x1 is the explained o here. So this is the header section which contains what hashing algorithm was used, as well as the type of Tolkien, which in this case it's JWT. The middle section has the payload or the data. So the payload is really to see all of this information is what I know about this user. So the more information we pack into it is, the bigger the section will get. Alright, and over to the right you see here they're showing you what exactly is included in this payload. So the payload can have led expiration date of the Tolkien or dayton time, because usually you issue a token for a finite period of time. So as long as this token is valid, then they don't want tough to login again, right? As soon as it's invalid, then they may want to login and get our fresh token and then continues. So that's what that lets the purpose that one serves. And then the pirates know with the signature. Usually the server uses the signature part to verify whether the Tolkien contains a valid information or not. So if we issue the token and we would want to verify that it came from us because anybody can really encode this kind of data. What they wanted to make sure that they have, don't hear encoded relative to our issuing key to make sure that it really came from us and it is valid in our system. So I hope that cleared up some of the, let's say the gray areas are what JWT is unaware using it. When we come back, we will start changing up or configurations in our API to facilitate its use. 29. Implement JWT Authentication: Alright guys, we'll comeback. So we're going to jump right into setting up our configurations for our JWT. So I'm going to create a new section in our settings file. I'm going to call it JWT. And basically we're just going to hard code some values that we know we'll need along the way when issuing and validating. All right, so I'm going to say issuer. And this means that I am the issuing authority. So you can put your application name or your domain name, whatever it is. I'm just going to say the uppercase on name here, OTA listing PA. So that means only when a JWC JRR Tolkien comes in with this issue or will I paid attention? What you will see more to that later on. And there are other things you can put in here. You can put in like the presets expiration time. Actually you can put a key here because there is a key value that is going to be used to settle the Tolkien. However, generally speaking, you don't want to put that key in the app settings file because of security reasons, right? So if you put it there, then somebody can see the app settings file and then figure out the key that's being used. I'm, I'm putting in a GUID valley here, but this could easily just be your name or whatever. So it's something you need that you want to use to verify our January the key. Alright, so alternatively, instead of putting something that's sensitive inside of the app settings file, because you don't want too much sensitive information in this file. What you could do is create an environment variable. Now of course, if it creates its own development machine, then you have to make sure you created also on the server when it is deployed. So a quick way to bring up the environment or setups or the environment variable is to bring up a command prompt, measure urine administrator mode. So if it is that this has happened on a machine at work where you don't have administrative privileges, then you have to make sure that you include this in your release notes so that the system administrators are DevOps engineers, whoever is doing the deployment knows what to do. So I'm going to say set x. And once again, this is an environment variable so discloses onto the windows level. So unless a hacker was, somebody malicious was able to access the actual and login to the machine that probably will never see this value are the ski art. So I'm going to call this key, give it the value. So once again, this is just not good. That's I generated. It's complicated enough. It doesn't necessarily have to be this complicated. But once again, it's a context is everything, alright? So whatever value you put there, you just make sure you wrap it in quotation marks. Let me do that. So key open quotes the value close quotation slash m and m, basically saying that it must be a system variable and not a local variable. So that's why you need to. Make sure that your admin, so you see it was saved. Alright, soul and all that. We have that set up. We can go ahead and create our service extension because we need to extend our startup. So once again, instead of doing it here, we will just go over to service extensions and creates a new method. This one we're going to have public static void. So I'll just copy this upon two, despite this bart and say configured dW t. And then we're taking the same parameters of the services. But then we're also taking I configuration. It's configuration which gives us access to the app settings configurations still Fred's for, for a little context of that. When we, let me see. So you see here we said configuration, get connection string, hi configuration, right? So that's what we're referencing over here. I've been figuring shown. So go ahead and in fluid anything that's missing. And then inside this file is where bits off magic is going to happen. So we're going to say var JWT settings is equal to. And then I'm going to call on the configuration dot get section. And the section that we're going to be getting is JWT sittings. Alright, so that's what let me just verify that. Oh, it's JWT apologists. I call it JWT. Alright. This is giving an arrow and I think it's because I included around with libraries so that mature, that's Again I configuration. I don't want extensions that configures and not the ultimate person. Let me try that again. And there we go. No arrows, all rights. So the secret key, no, I'll say var Ki is equal to and then I can call an environment dot, get an environment variable. And remember that we set the name of this environment variable, just know they're bringing buckled my command prompt. I set it to C0. So whatever you will use there is the name of your environment variable. So t. Next, we want to say a services dot add authentication. So I'm going to add an authentication options with options. Sorry, let me just get this. So they say OPT or you just say all but the lambda. And then I'm just going to open and close brace because we have quite a few configurations that we were going in here. It's anytime you have multiple lines, agendas open the curly brace and then each line ends with a semicolon, someone to say all dot default authentication scheme x0 equal to. And then they have JWT beer defaults, soul, what's not here. And I think I need a few libraries or song from. From New gets. So let me just check barrels of so there it is. Need to include the Microsoft is being at core authentication, the JWT Bureau. So then we go ahead and get that. Know it's included JWT Birra defaults dot authentication scheme. So this is basically saying that I am adding authentication to the application. And the default scheme that I want is the JWT. Alright, so off the but one somebody tries to authenticate, check for a bearer token. That's basically what that is saying. And then default challenge scheme is the same thing. Alright, so check for that for authentication and challenge. Whatever, whatever information comes across, challenge it based on the JWT standard. And aware extend is I'm just going to remove the semicolon for a bit. So I wanted to see in the next line dot add JWT bearer. And then this one's again is going to have options. So I'm going to do my Tolkien lambda and then open and close curly brace. And image is fixed the indentation, right? So then we say all dot Tolkien validation parameters. So there are quite a few parameters that you can set up along the way. Each person might be different. Once again, institution might be different. So what I am doing is those educational, but in your enterprise setting, you may have other needs than what I am going to portray here. So if that turns out to be your situation, then you just act accordingly, right? So a new Tolkien validation parameters. And then we are going to know all outline some of the parameters that we'll want to use to validate that this Tolkien, you know, should grant somebody access. So then here we can see, Do we want to validate who issued the Tolkien? That's generally a good idea. Considering that we went through all the trouble of saying here is the issuer. So that means if somebody put some other value there, then we're saying, well, if I know the values there, then it should be invalid. Boolean wanted to validate the lifetime, right? So this way, we will reject the Tolkien if it's if it is expired, will automatically rejected. So do you want to do that? Yes. And then another one that we probably want to do is validate the isu issue or signing key. And we already established that this was the key value up top here, right? So on to make sure that it's always the correct signing key. And then we continue. And then I went to see a valid issuer. Or the valid issuer for any given Tolkien would be JW settings, JWT settings, which is a convict section. Get section, all of that. And then it would be issuer, right? So their value is set for the issuer. I want that dot value, their goal. And then let's see the issuer signing key is equal to a new symmetric. So no, we're going to be hashing. And so, and that's why I said it can be a complicated Valley, doesn't necessarily have to be because when it's going to set it up, it's going to, we're going to be hashing it anyway. So you say new symmetry, symmetric security key. And then we encode. So you see, even with my very, very complicated one that was based on a void, we're encoding this and then we're going to hash it again afterwards. All right, so as I said that it doesn't necessarily have to be that complicated both encoding W2 if get by its or breaking it down into bytes. And then we pass in the key value that we got from the environment. So the most important parts of what the key is, don't put it in the app settings, right? It's thrown up on, it could've gone there. But, you know, to be a lot of abundance of caution. You put it in the environment variables. I Alf puts it in the app settings before, but then that was far very internal application and not necessary to public facing or and so we'll just go ahead and include any missing references there. And then I think that's just about it for validation parameters bullet once again, based on your situation, you may need more validations than I am putting here, right? So this is all I'm going to use, semicolon, semicolon, and then that's it for our extensions. So no, we can go over to startup and we can call on our configured JWT services dot configured JWT. And we have that configuration object being passed down the line, right? And then we kinda stop bill just to make sure everything is softer, successful build we can continue with our tasks. So the next thing that I wanted to do is create some functionality for the validation and the issuing of the Tolkien, right? So I'm going to go up, I mean, just collapse everything in the project are at. And then in our well, I repository and repositories. So what I'm going to do is create another folder called services. I just wanted to make sure everything is well, segregates its unaware watches. So services would be for extensions, right? I went to add a new class. I'm actually, I'm sorry. I should have named this eye off manager. So I add a new class called it off manager. You end up doing exactly what I Adidas renamed the file and it will automatically, automatically renamed that. But then sorry, it's not a class, it's an interface. There we go. So in this interface, I wanted to have a task that's going to return Boolean. And I wanted to call it validate user. And then this is going to take the login user dto disclosure. It's user Nietzsche. Oh, well, uniformity purposes. And we'll go ahead and include any missing references as usual. And then I'm going to have something else that will create and returned the Tolkien, someone's recall it creates Tolkien. Alright, so I need a class to consume that read. Someone's going to go ahead and I don't want to call this one off manager. This one is actually a class which is going to inherit from its interface namesake, which is then going to see these implements, the methods that you told me I should have. Before we move on, we have to make sure that we register our service in our boots trapper here in the style.css file. So we're just going to say a services the odds caught and have eye off manager mapped to off Manager. And we're once again adding into sculpt. So that's very important. So we're going to create this Tolkien. So inside of off Manager, I am going to be putting those two. I'm going to be injecting tool things. So I need my, Firstly, I need the user manager, which I can easily get from cones, my address. I need that exact instance of user manager, right? And just go ahead and include the missing reference. And I'll also need to inject an instance of the Configuration Manager. So just go ahead and make her presentations for those and then finish the injection. And once that's done, we can continue. So let's start off with validating the user. That's a lower hanging fruit. So let's just deal with that 1 first, right? So when we want to validate, the user would basically say, we wanted to go on to say Those this USA exists in the system and is the parser acquired? There are. So I can say var user Z equal to awaits, user manager dot find by name a sink. And then remember that for this fine by name basically means fan by the US in India it is, it's asking for the username. I were using the email address as a username. So we're only asking for email address into dto, but systemwide is where story that has a username also, right? So I can just go ahead and do that. And this is saying, oh, so o, it means I need my asynch, right. So anytime you annoy, you read a perfect oh, wait statement and you're still gets into red line. Just double check. If you have the async, it tends to snip. With practice it becomes permanent. So then after we check if we have phone this user, so this is willing to return to users object on storage here. Then I'm going to see, and I'm just going to, instead of writing an if statement, I'm just going to write like a ternary operator to say user not equal to null. And so just double-check. This is not the Turner scheme and this is just a logic statement. So return if the user is not equal to null. User manager dot check password async. I always say user dot password. Sorry, not user, user detail. Because we don't know the password hash. So user dto dot passwords, so this is automatic. Gotta go in to see if this password is valid for the user that is being checked. So if we return somebody with a username and the password is valid, this is going to return true or false based on the old comb, all of that. And what we're missing here is all we need to use our objects. So I need user como, user needs yield up buzzer, go. So it's going to check the password, see if it's valid and disordered. You would have something if that username existed and then we would know it's a valid user item. Let us flesh out what happens in the create Tolkien operation. So here we want to create an object for assigning credentials. And I'm going to on to get what we'll call claims. And I think I need to include her friends. Alright, so forth, create Tolkien portion or we want to do a few things on to create some signing credentials on to get claims, and then we want to add them to the token option. So I'm just going to write them line by line. Get the signing, get the sanding credentials, get Canadians, and then create Tolkien options, alright, where I'm going to be, we have to create these methods so adorable there are lands, right? No. But then at the end of the operation, I'm going to say return new JWT security. And more than this needs something so did OUT security token handler, that's to, so we have to include this identity model, Tolkien's dot JWT, this, and that's a method or a class or not. Right? Tolkien, which is also a method, but it takes the token options. So whatever we get back here is based on what we get back here and BSL would get but there. All right, so let's start off with this one. So I'm just going to hover over it and generate the method for it. And it can be private so you don't need it to have any public operations. So we are getting the sanding credentials. So the first thing I need to do is get the key. All right? And we're going to do a similar operation to what we did in the service extensions to get the key. So it just went over and copied and pasted those two lines. The key get, it's gotten from the environment variable and then we encoded to get secrets. And then the next thing that we're going to do is just return new sane signing credentials. And that's going to have the secrets. So secret here would be the encoded version or its secret comma. And then we let it know that the security algorithm used for this was the H M saw tooth 5-6. Alright, there we go. So that's taking care of descending credentials, right? No, let's do the get claims. So I'm just going to hover over that one, do the same generates method stub for it. Alright? And then on, I just noticed that this is of type object, so I'm going to make it very explicit that it is signing credentials. That's the return type of this, right? I'm sure object would've worked what I'd just like to make sure everything is strongly typed. So this one, let me just go ahead and make it a sink. And it needs to be a task that is going to return a list of claims. Alright, so the reason we have to go through all of this is our claim rather not claims. There is a we have to go through all of this. The defendant types that we said var for explicit up top here, then it would have inferred what return types the ports, boats. Because we said var, it doesn't know, so it's just being very vague. Alright, so let's go ahead and get the claims. So I'm going to declare a new list. Var claims is equal to a new list of type claim. And we're going to add a new name. And then the thing would claims is that these, these are the bits and pieces of information that really tell who are what you can do, right? So I claim to be this are claimed to be able to do that. So those are the things that we want to make sure are included in our application or in our toolkit. So the first theme that I wanted to add is the claim types dot. I went to look, there are a bunch of 0s and I'm so these are all claim types that are there. See role is there you can add multiple rules, email, all those wonderful things, right? Someone to see Nim. Nim generally means username, email, self-explanatory, etc. So if I said I wanted it to either clean type name, the name of the user who was just validated which someone's out to change something here. So I am keeping the user locals of validity user, which means then I would have to try and pass that along. So what I'll do here, create another variable here of type APA user, and I'm going to call it user. And then instead of localizing user in invalidate, I'm just going to do that so on. Where in the context of this class, we will have access to the user data. That's his idea, right? So let's continue. So name is Lynn to come from user dot and we'll just use, well, we can use username, right? Like for lack. So in a situation where you wouldn't be using the email as the username, then you have the username to use as a named clean and minimum. You'd want to have that, right? Then we can say var rows. And then we can our weights. And use user manager to get the roles for the users. So there's get's rolls a sink. There we go. I would just pass into US AS it's automatically going to go fetch all the rules for this user and return them in the form of list. There we go and list. And then for each of those who want to add, then, so for each rule in roles, we want to add that claim. So I can see claims dot. And then I will just say new claim the same way we did it here. And just say claims that add new clean but then click type would be role. And then the rule coming back order or to be added would be ruled from our loop. All right, and then after all of that, and we build it up and once again, based on the claims that you wish to put in on, you can see all of the potential claims here. You can put in as many as you want, right? Once they're done that you can just return claims. So that's Troodon and one more to go, right? So I'm just going to generate this method, still know which is going to combine the sanding credentials and the claims and create the actual Tolkien to be issued to the user. All right, so here the return type would be of type JWT security. Tolkien writes, JWT security Tolkien, though, so that we're very explicit as to what it should be. Now instead of this method. We're going to be seeing that var. So I have to get the sittings. Var JWT settings is equal to, and I really don't want to retype this. Let me see if I can just get the quickly here. Arguably, I could've retentive, but that's fine. Var settings is that though we say var options are Tolkien options is equal to new JWT security Tolkien. And then we have to use this constructor. So it dawned on him to one of course. So we're going to fill in certain parameters. So I went to specify that the issuer that I want is coming from the JWT Settings section for the valid you ease your just like what we had here, that is the issue that we want. So we put that as an issue. Are there the next one would be the claims. And then the claims would come from our list. Claims, withdrawals, boss loan in the parameters here, right? And then we want to set the expiration on. Say expiration is always good to sit. So it's actually asks you for an expires value. Now you could set 15, include set ten, mg, and it could do that. Or you can just modify the settings file and set the value there, right, so since that's where all of my hardcoded values are going, I'm just going to keep it uniform. And so I'm going to just say get that value from the settings file. It's in the section called lifetime. So that means this value, this Tolkien once, once created, will only be valid for for 15 minutes. That's right. And then the sanding credentials, which we set already or actually passed down would be here. Now once all of that is done, we go ahead and we return. Our options are, let me name this more, more appropriately. This is the token because this is the creation of the Tolkien's or returned into Tolkien. And then that is Tolkien, right? Then we serialize it into a string and return that string null. We've done quite a bit of work here. And the one thing that we probably need to do afterwards is to make sure that we and I'm sorry, I'm just seeing an error here with the configuration. It was her own one. And just make sure I have the right one blob built. So I will say and that we've done quite a bit here to get our Tolkien things up and running. So what we want to do is, I'm sorry, so this is good. So because of her own configuration, I wasn't seeing this arrow expires should be. I did. And I only put 15 minutes. So let me, let me redo that someone to save var experience SHA-1 is equal to, I don't watch should really happen is we say datetime dots null. When was a Tolkien asked for, let's add a few minutes. So whatever it is, whatever threshold you want. So if it is de minutes at all, was you just say add that appropriate ones, it's odd minutes. And then we would put in the value. And value here is string. So that means I need to do something like an int converts dots tool. And as I said in 32, or does this, does this require double? I think that requires double. So let me do I'll convert to w instead brake line and close that. So I'd minutes converts to Bobo. I'm sorry. Yeah. There we go. So we do that converts a double-ended expires is getting the value from the exploration, right? So at that point, we know when the Tolkien would no longer be valid and I'm missing a semicolon here and let me do a build. And we have no arrows. So I will sing when we come back, we will explore whole authentication. Actually our authorization actually won prevents access to our resources and then to how we actually setup the endpoint to authenticate the user and easy to talk and accordingly. 30. Protecting Endpoints: Alright guys, welcome bucks. So coming off the heels of setting up our authentication manager to issue generates an issue. The tokens, what we want to do is actually finish up our login endpoints to the to and where we actually validate the Tolkien and allow or deny access to anybody passing in this token, right? So the first thing that we wanted to do is inject our newly created off Manager service so we know how to do the injection areas. They can just go ahead and hit pause and go ahead and complete this injection operator. So once you've added the new three lines, one for the private property, one into the constructor and up initialization. Then we can go about creating or login endpoint. So you would have already commented on the login endpoint. You can uncomment it and I'll already have the revised version of it on screen. So let's just go through it together. So what we want to do is log on to validate our requested or the data coming in detail. Then I'm going to say if the off manager validate user, if not thread, so it could easily read, he says equals false incase, you need to C sharp. If not, you just put the exclamation sensor. This means if it is not a valid user than return on Author as because, well, if you try to log in and you're not a valid user, then you are not authorized to go any further, right? Otherwise, we're going to return accepted are okay. Whatever it is, I'm seeing accepted, accepted, new and a new object with, with an expression called Tolkien. And it will take the value of the token that is created. So we say a weight on the score off manager dots create Tolkien. So remember that, that's what we would have set up in our Auth manager. Just null create Tolkien goes through, generates all of these bits and pieces of data, and then returns the Tolkien. So that's what that payload will have, so on to go ahead and test that functionality. So let's revisit our login endpoint. I'm just going to use soccer for these parts of its are the striatal it and put in a user that no, I created and is already registered. And then I'm going to click Execute. And let's see what happens. Or it's, and we're getting a token response. So you see this big string, tolkien, that's by virtue of the experts and we'll put in a custom object. And the value being passed is the token that is here. So if I, if I did this token and go to our website, look at what's in tokens. Paste it. Then we will see here that we have the algorithm, we have Traviata example.com. That's the claim for the user. Well, the role. All right, and we have the expiration time. And if you hover, it will show you exactly the time from when it's issued and the issuer. Alright. And then if we wanted to go as far as her friend deceiving, so we could do that, but to already have the mechanism to do that internally, so we don't need to do that here. So now what I want to do is experiment with actually preventing somebody access to our endpoints. So I'm going to use our hotel. To controller for that exercise. So let us say that the ability to get the list of hotels, everybody should be able to do that. We should be able to call it without authenticating, which is what we've been doing up onto null. However, we want to add an authorized flood or annotations onto the call to get to one hotels details. So we just put on Authorize. And actually you could extend the, the annotation here for the HTTP GET and add authorize right there. Alright, so you could do it either way. So if you have this one, you don't need this one. Personally, I like to separate them. So of the HTTP GET authorize and actually like or prefer to put it at the top. So as I see it, I know it's an authorized endpoints. Alright, so what we want to do is test our call. So this endpoint unauthorized and authorize. So this goal. And for this activity I'm going to use postman, someone's had firstly test the one that we haven't authorized just to make sure that it still works. Alright. There's a list of photos, three hotels. Good. Now I'm going to test the one with the end point that requires an id value, right? So when I click send, it's going to say 401 unauthorized. It's not saying 401 on Author as because I didn't log in or whatever because I mean, this is already authorized and recently the default schema to C, I need to see a Tolkien in order to authorize are not solid. That is happening automatically. If we have an old Tolkien in there, which I do, this is a token that was issued more than 15 minutes ago. Then it will automatically also deny access. So when an Tolkien is issued, and then it takes spires, it is the owners of the client calling up application and sorry to go and fetch a new toolkit, meaning goes through the login process again, gets a new token and then come back and try and access these endpoints. Alright? So in Postman, what we want to do is go into authorization and choose bearer token from this dropdown list. Then we provide the token that we have, which is the fresh Tolkien. And then when we do that, and I'm still getting a 401 unauthorized, so that means there is some configuration that is missing. And let me go more than likely it's in the startup dot cs. And I think I left off one of the middleware, so I need to add up. Use authentication right here. Alright? So make sure you have this. Use authentication and order matters in this situations, authentication, then authorization and all of that before they are up, not NVC. The different.NET Core versions may have different middlewares being included. So as long as you get that general theme, you should be good. So let's try that same request again. And we're having much better success. All right, so we're getting us Status 200 OK. and we're seeing the one hotel that we requested. So know you see that we just protected our endpoint because if I remove this and say In all off and interests and again, I get a 401 unauthorized once I include the Birra Tolkien, I get the status 200. If I modify this spirit, Tolkien, then it's unauthorized because the Tolkien could not be validated against the inflammation was encoded and put in originally. So that is how you can go ahead and harden your API. And once again, this, this JWT method is very secure because this payload, yes, it can be decoded, but it wanted shouldn't contain any information that is too sensitive and information that's it contains should be information that if you see it, it's off. No major consequence to API and the underlying infrastructure. However, it is enough for me to verify who you are and that I am the one who gave you access to the system. 31. Review and Add Changes to GitHub: Welcome back guys, where it's another significant checkpoints. And every time we get to significant checkpoints, we go ahead and check in our code so you can just go ahead and write your check in message and then commit all and sync. And once that is completed, then we will move on to our next exciting activity. 32. Construct POST Endpoint: Welcome back guys. In this lesson, we'll be dealing with the HTTP post method or verb that allows us to create resources or new records in our database. Though we've worked with post previously when we were sitting up our login functionality in our controller, we did kind of experiment with the post and we explored the fact that we can actually pass in data in the form of the body, are an adjacent objects that would get deserialized into whatever object we have settled for it. And that way, no sensitive information needs to go across in a URL RNA visible manner. So what we're going to be doing is setting up the post functionality for our hotel. So that when we are creating a hotel, we can ask the user to send over all the details soil Hotel in the form of a JSON object and then we pass it on to the database. So I've already prepared the methods, the web or verb HTTP post. And we'll be returning status 400 status tool one as well as status 500. Now notice this is 2l one and not 200 because 2-1 means created. So we'll be indicating two, the calling application or the client that yes, whatever you are requested to be created has been created. So let us get started and now the first thing that I would want to do before I go ahead and create anything or bring over any data into my database is to check if the data coming over is valid. So what I wanted to do is put in an if statement here to say if not, model state is valid. So we did something like that. I believe when we're doing the login where we said, is the model state valid, meaning everything that I've said is required. Is it there? If not, we returned the butter twist. So we're just going to do the same thing, replicate that step here. But I'm seeing if it is not valid, then you're going to love the air and say that there was an invalid post attempt in that method, right? And we return the bad request. Otherwise we want to try and operations. So we have our try catch. And the uniformity of our code is such that we can actually take these old. So you start seeing that we're kind of repeating certainty is because all these things, what if we wanted to change a message? They would have to change it here, changed in this method GnG tier. And then as we expand, we have to have more touch points. So later on we'll see at whole weekend, abstract out all of this repetition. But right now I just want to make sure that we understand the concepts of timed. Alright, so we'll just go ahead and modify the error message and know you can try or operation. Now what are we going to try? The first thing that I would want to do is to take this dto. And if we just review this detail, it has name, address, rioting, and it's expects a contrary ID. And then we have hotel dto, which has ID and country. So once again, the reason we're not using hotel detail is that we don't need the ID value coming across with the create attempt. So that is why we only have the fields that we absolutely need values for outlined inside the Create version of this dto. Now once I have the detail, what I want to do is map it. Someone just say var hotel is equal to mapper dot map into an object of type hotel, which is a data object, and mapping the contents of the hotel. The t o. Next stop, we're going to call on our unit off work. So I am going to see underscore unit of work, dots, Hotels, dot. And then I have in cert whatever inserting my object of type hotel. Because by the time it gets here, whatever validations you need to put in, you can put in. So here I'm just validating a molecule states if you had other things that you needed to make sure are in place before it gets us fire as trying to insert it, you make sure you do all of those checks and balances and return the battery quest or whatever, Aristotle, still a client before you actually start in insert. And even when doing the insert, if there's an exception, we're still going to return something except it will be FIFO hundreds since the area is probably on our side. So after we call the insert, the next thing we need to do is call the save. Notice. When we were just retrieving, we could just do a awaits that get there's no save. However, on this occasion we're altering the database so we have to commit the change that we're making afterwards. So that is why we have to call the save. Now after all of that, we need to return something nice. So what am I returning? Ness, I'm gonna say create, Ted, No, I've created enough, created at action right there, actually uncreated at root also. So they all returned the 201. It's just that when you say created, it's just 201. It, however you can say Created out to route and have it call the endpoint, get told TO with the ID required, say actually returns, they created objects to the client, which I think is useful. So I'm going to go with created at root. Then I have to specify the name of the route. So in this case, I did say I wanted to go to get Hotel. And then after that, I have to specify what parameter values this endpoint might need. So if I look back, I get home TO IT needs an ID softer specify a new object. And it's going to have a field called ID, and it's going to be equal to hotel dot id. Notice hotel now total dto, hotel ETO does not have an id value. However, after this operation, this object will get updated with its ID. And then that is what we will pass along. So let us take this one for a spin. But just before we do that, before I get to head off myself, we need to let this rule nor that it has this name, right? So even though it has the name, we need to let it know that it gets operation that goes by that name, not necessarily roots book by that name, right. I can just append here and say Name is equal. So this is like a little internal nickname note to see. This is your name whenever somebody at your siblings, sibling being another axon calls. So lets us try that's again. All right, so we're going to test this one in Postman. And I already have an object here, so I actually copied this object from our previous getText. So we already established that the ID is not required. However, just going over to slugger, just to show you what swagger is going to cure a boat. When we look at the post for hotel, it's showing us that this is all it's going to be terrible. So even if we send over extra information, it will be ignored. Alright, so that is what our object needs to look like in order to go into our posts. So using postman, I'm actually going to test it with the ID and let's see what happens. So I'm going to click send me. This axon is on post. We have our endpoint and then click send. And we're getting this era both system invalid operation Nauru, much is supplied values. So that means we need to restructured the code or on a createdAt r2. So going back to the code, let me just see what's overloads are there. And we have the string root name where the objective value, I believe I'm missing the actual object. There we go. So comma and hotels or passing over the id and the actual object to be displayed. So let's try that again. So the same tests that does give an error, I'm going to try it again. And there we go. So look at the difference between the two payloads, where getting back our hotel object with the ID value of six or x, even the five is 5 here, it's five here, right? So just to show you that this didn't cone for anything, thanks to us not allowing them to submit that data. So that's another reason. It's a good idea to use details to cantos sanitize what can come into your API. Now in addition to displaying the newly created required another advantage, those using created at Rutan pointing to the end point would be that in the headers we actually return the location where they can go and fetch this record. So you see, it did have a certain purpose if I had just, you know, the client, if they look in the headers and just get location after I've returned the data that they can actually just use that and do a get operation and retrieve their record. But of course I'm not authorize. So you know, that whole shebang already that have to go through and do all of that. Now on the point of being authorized, I don't think it's harmful to allow somebody to retrieve a hotel by ID, right? So we did authorize it initially because we were testing. However, in practicality, I don't think we need to authorize, get told TO. If we allow them to get the listener should. One, however, I do think that it would be good to authorize who can create. Alright, so it's up to you with business rules and your needs will determine where you put the author as an home security, you enforce our own year endpoints and operations. So in this situation, I'm going to authorize creates hotels so you have to be authorized. And to me it much worse, if you are not in the role of admin, then you shouldn't be able to do this. So to enforce rules-based authorization, I can see roles equals and then listed out as many rules as I want to support. So if I say authorize Rules, administrator, that means if you are authorizing, gets it Tolkien, but you are a user, not an administrator, then you cannot carry out anything you're still not authorized. However, if you're an administrator, then you can go right ahead. So that's this whole once again, you can go about enforcing one. What end point do you exposed to John public versus an author, authenticated user? And then by extension, how do you extend these functionalities to which authorized group of users who can authorize based on policies, rules. And there are quite a few options available to you. If it does press comma, you'll see that you have the authentication scheme. We could make one JWT, another one password off, et cetera, et cetera. You can enforce a policy and you can limit it by roles. So there are quite a few options for that. So, right, no, I'm going to challenge you once again what we just did with create hotel. I encourage you to try and do it with the country. Make sure that you test it and that you get back your country successfully. And we'll compare notes. And we're back. I hope you paused and attempted it. If not, then go ahead and pause. No, but I'm going to walk you through what I did. And really and truly you will notice that the code is almost identical. One where in the country controller we have the same authorization measures. Once again, your context may be different from mine, but we want to just make sure that we secure the endpoints accordingly. We are doing an HTTP post will have similar return types to what we did with the hotel, except for the action I'm going to call it Create contour passing in the appropriate dto. We validates the model state firstly. And then we go ahead and add just in the same fashion. And then we created at root get contrary possible the object. And we made sure to add that name here. So you see, once you get the hang of this, unless you have some extreme circumstances, we have to do extra computations and calculations. And even then, it would just be a matter of mapping over r. Well, yeah, you wouldn't probably wouldn't get the calculated values through the detail. So you'll map it to the object type. And then you do all your calculations, and then you insert and save. So there's really not that much to creating resources in your API. 33. Construct PUT Endpoint: Welcome back guys. We're continuing our API development journey and we'll be exploring the PUT Verb. This tire. Now, put is similar to the post, except it is mainly used to either creative it doesn't exist, or update if it doesn't exist. So let's get started. And when we tested you, that will make a bit more sense to you. So the first thing that I would want to do is to replicate the kind of restriction as to who can access the put to me. If you can't creates the niche shouldn't be able to update, right? Once again, contexts, rules, but I'm just going to authorize. And I'm just going to authorize. I'm not even going to make it ruled based. Right. So the administrator can create more than once they're authorized. You can go ahead and create a you can go ahead and update, sorry, regard to self-care rule. Alright, so the next one would be HTTP port, and that is our new verb. And more or less are going to have the same return codes except BY doing something differently for this one. So let me just comment this one nodes and when we get there and then we'll adjust it. So we have our method's job. And I'm just going to copy. So it can move quickly with prepping this method stub, right? And this one will be update hotel. Now in terms of the detail that will be used for updates hotel. Well, firstly, we need the parameter for the ID. You know, there are two schools of thought, or maybe three schools of thoughts on this matter. But let's say two school of thought. Number one is that I need to have the ID in the URL, just like all we had were they get right. So I need to, I need you to pass in the ID with the URL. But then one school of thought would say that the detail also needs to have the ID. So that means the client needs to pass in the ID with the URL and positive in the body of data to be updated. Now, that is one potential validation point where you check if the id that was sent in the URL matches the ID central wherein the payload or the dto. And if there's a mismatch, then you return me the butter request. Alright, so that is one method of doing it and I'm just talking through it before I actually do it. The other one would be that the detail doesn't need to have the ID because the id is going to be in the URL. So I expect to to pass over the URL with the ID of the record you wish to update. And then you just pass me the updated information and I apply it accordingly. Now, that is also an acceptable chair enough thoughts, they're both acceptable. Once again, context rules. So some of you will feel more comfortable with the double-check, having the ID in the URL and the body. And then you check, and then if they don't match, then your rejects the attempt. Some people don't mind having it one place underscoring along with operation. So we are going to take the approach where we have it one place and not in the dto. Now because of that, I could. Use the creates hotel dto. But then to me that would kind of violate the single responsibility rule that I've been kind of promoting. Because when you say create Hotel De Jiao, it tells anybody reading the code that this is for creation. Why is it in the update? And now you have two options. Again, you could either rename this to maybe something like upsert, where this detail serves a double purpose off creating and updating our inserting and updating, hence the portmanteau upsert, right? But then once again, still single responsibility depends on how strict you want to be. You could also realize that you might have varying fields in the 2D deals because what you would accept for creation, you might not expose all of that for potential of it. So you want to consider all those things. So what I would do is actually create a second details. So I created another one, I call it update hotel VT0. In this context, everything that is here for the creation is fair game for updates. Alright, so I'm not going to go ahead and create another one at all. I did was just inherit. So I'm just doing this because of the single responsibility concept that I have in mind. I DO Aswan to make sure that when you see Update total detail, you know what it's far. However otherwise, what you probably want to do is just be more particular with the fields that you expose in the update dto. And we've seen where that can help with some control already. So I'm just going to go ahead with that level of inheritance. Once again, that's up to you. And we just wanted to write clean code and make sure it's readable at the end of the day, right? So I'm taking the ID in the parameter and then I'm taking the fields for the update in the body of the request. So I'm going to start off with my validation checks and when to say if not model states, dot is valid, if it is not valid, or if the id value sent over is less than one, does I mean it should be at least one. Write it to be 0 are negative. So in either situation, I just want to log and return battery requests that something is wrong with your attempt. Alright? And then we can move on to our try and catch. And then we know that for the kids section, we're going to be logging the error as well as returning the status 500. Alright, so let us see what we are going to try. In order to try, I need the original record that needs to be updated. So what I have to do is actually save var hotel is equal to wait Unit 04, Tomatoes dot, get me. Direct Cards, puts in my filter where the ID is equivalent to the ID coming in through the parameter, right? Then I can do another check. I can see if Hotel is equivalent to null. So I couldn't have done a search. Maybe that Boston, the ID ten our lives, six hotels and a pass in ten with something to update. I'm going to try and find it, but I need to make sure that I actually found it right. So then I would probably. Bud requests. So let us say, I do the same thing here, but in the butter quests section. And we're going to see submitted did is invalid. Alright, so there's no model status, so somewhat off the record with that ID Xist are not. And you could actually even just extend the unit of work to do the exists. But what I'm doing is just getting it one time. If it, if it's null, then we end it. However, if it is not null, then we can go ahead and try to do our bit. Now I'll quickly to kind of equate the tool would be to use the mapper dot mob. And then I can see at this point what is the source, so the source series Hotel. And then I'm going to say, I want it to be norm, sorry, the source would be the water dto. My apology. So a hotel dto is the new source because hotel dto has the latest information. And then I'm going to see Hotel to the right. So if we look at this mapper overload, it takes two things, the source and a destination. And then what it's going to do is just mop what's in the source to the existing destination. So effectively we just said whatever is in this, put it in that if there are two fields that are not equal, then please update this all with the fields coming from the detail, right? And then we can know see Unit 04. Not a problem is that we did not do any tracking. So if we were doing trucking, we could have just said save boats. We are not trucking stuff to see updates. And then pass in hotel. Right? And then we, you know, it's all four save. So just one extra line of code, not too bad. So the thing is, I remember I was explained that with the update method, what we did was to see, please pay attention to whatever entities here, touch it and change its state to modify it so that it's a modified. So when we save, it will be kind of in the register to be saved or updated, right? If we had not r If we had made the tracking optional, then we wouldn't have had to take that extra step of saying updates. We could have just done the change and see if the because trucking is actually by default. So I am just explaining that little bit too cause I didn't mention it. So let us, after we save, we can return null content. So an old contents seems like a butter apply, but it's really a tool for which is anything into 200, which is good, right? So that's good because I don't want to have anything to tell you like, okay, you sent an update. Ok, there is nothing more to do. You're good to go, right? So that's what the no content is really far. So coming back to the one that we commented it taught, they'll say status to all four. Let us test that. So just to bring your attention to what swagger is doing, you'll see that each type is nicely color coded. So if the word wasn't enough, then you see the color code put is nicely stated there. And there's our dto with the fields, and it's expecting an id value in the parameters. Alright, so let's use postman. And I'm going to go right up to the last total that we created. So this was our successful post attempt and we got it back. So the ID value is six. So I am going to say Put is my verb and I'm passing in seeks as the ID value, and then I'm going to put a comma. This was misspelled. It's a tiny tiny change her, but as we'll see, the comma underwriting isn't really five, but it's 4.84 moon pilots Jamaica grand resort. And while the countries Jamaica. So let's leave that. So let's go ahead and send and see what happens. Right. Method not allowed. And oh, I think I know why we didn't put on the parameter alone answer on the port. So the same way that we have this on the HTTP GET after specify on the put, that it should take that parameter. So business was at that. And let's try this again. So buckskin Postman, I think that should get the 401, this dimer. That's better. So the 405 method not allowed means that either you have something wrong with their request or your end point needs to be fixed too much. Holder Quest should look. So just know that's what we run into. We had the request properly, but then the endpoint was lacking. Alright, so it's good to see these little things along the way so that when they happen you can take control of the situation. So what we need to do is get a Tolkien. And I believe I still have my user request over here. So it's really cool with both money can always go back and get previous requests. So let me just grab my Tolkien, come back over here, add it to the authorization header, and then try this again. And it's hitting my sits a breakpoint there. All right, so let's continue. And there it is tool for no content, so it has successfully processed the requests. What is not returning any content? Well, no content, but once again, a tool for is a good return type. So let us now go over to our previous Git and see what happens. A Tolkien. So let me just go ahead and put this Tolkien here and do the get. And then we will see there's R comma and there's there 18 chance for 4.8. So as far as we're concerned, the put works? No, just building on what do put does and doesn't. Do. You see if you miss something? Let's see. You have some fields that are not required. All right? Right. No, it's hard to test what I'm going to go ahead and modify this dto. So let me go over to create needs you, and I'm going to say that the address field is not required. Alright. I went to restart. So why this restart and let me just explain what's wearable to do. The put is always going to replace the data. The only thing it does is it replaces the ID pretty much right? So anytime you're going to do a put, you have to be mindful that whatever data is there, it is going to use it to replace, say if I don't provide an address, let's say to address all of this payload, it's no longer required. I don't provide an address. What's I'm doing the put I'm doing the update, right? Same hotel and I'm doing the update I send. Alright, so I'm getting a tool for no content, but look at what happens to my data. So notice we had unaddressed volume. No address is null, say half. To be careful whenever you're using these kinds of objects are at least to put because it's always going to replace it with the data that he got. So it is on you to make sure that your validations represents the data quality that you really want from your client application, whether you are building a plant or it's a third party who is building the client. The API is yours and you have to set that standard because it not be required, I load a null value to be there. Know once again, that could be good or bad based on your situation, but that is how the put will work. So I'm going to encourage your retinal to pause, replicate the put endpoint for the country's controller. And then we're going to look at something else as it needs to the put and how we can enter a bit more needs of January alone right now. All right. So we're back and I hope you paused and attempted it yourself, but I already did the update country and I'll just walk you through quickly. There's nothing here, that's all. It's off the ordinary compared to the hotels. Everything is fairly standard. We have the create contrary detail which I need to update. There we go. It's a good thing I'm doing this review. Alright, so we update contradict to contradict you. And everything else just looks the same way. No. One thing that I want to point out with the update contradict to you is that I have included this property which is a list of hotels. Alright, so yes, arguably, I could put it here and then remove it from this one and then let the country dto inherit from the update contradict TO sensitize all of these and the list. So this would get everything. You could do that. But then this is just driving home the point that you really want to kind of keep your details as unique as possible. Because then, you know, you may have shared feels shore, but then you may have unique fields also along the way. Now the relevance of this list of hotels is that I can actually use my put to update, accompany and also insert new hotels are related hotels because remember that hotels, This means that one country has a list of hotels, right? One contrasts many hotels, which is why we can reference them by list here. Alright, so let us explore what that would look like. So if I go over to my swagger documentation and then look at the potential payload you see here where they're showing me that I can put in the name, the short name, and then an array of hotels. And then I can put in details for the hotel. And of course the hotel has, but then shall details for the country. And this is what they really meant when they said it could become cyclic because it's just one big thing after another, after another. However, we're going to try this out. We're going to insert a new hotel. We're sorry, a new country with a new hotels. So I'm going to just duplicate this post-secondary clique, say Duplicate tab, since I already have it there. Before I do that, let me see all of the countries I house. I don't really have any tests with country. So let me get all my countries so I can see my options. So I have jamaica, Bahamas, and Cayman Islands and see if we need to update Cayman Islands because of Cayman Island, it should be Island Zoo cosmetics, but let us go ahead and update that. So I'm going to let me just get my bearings. So I'm going to take the payload from the sample are from our swagger. And then the country's sorry, the country's ID that I want it. I'm just trying to find where was the conscious ID is three. So the name will be Cayman Islands. The con, the endpoint would be country slash three. Alright, the short name still CI. So once again, you have to provide the value that you expect to have their afterwards. All right. And then I'm going to inside of the hotel's section, remove anything that I really don't want. Alright, as almost all fact, let me go back over to the detail. I just noticed that I'm listing old hotel dto here, so I didn't say what could consolidate materials are good reason I'm not consolidating. I said Hotel dto. Hotel dto then puts in the id. But if I'm doing an insert updating Cayman Islands while I want to insert a new hotel automatically, which means I don't need the ID value. So this detail is actually incorrect. What's I should have here is create. Hotel VT0, which is a better representation of the data I wish to collect. And that would also get rid of the excess feels like the country and the extended list of photos. So let's try that again. All right, so now when I look in swagger and I look at the schema that looks much better. So you can see details are very important. What do you require from your user? Makes sure you expose only that. So I'm going to take this corrected payload, go back to Postman and this will be far less confusing for me, right? So let's try this again. This is going to be Cayman Islands with i capital I, right? The short name is still CI I have to provide that. And then in the hotels section, I can actually list all the hotels are objects of hotel. So this square bracket means area. Then the curly brace encapsulates all the object properties than I can say comma and list second OSU comma and continuing to put them in, right? So here I'm going to put the Ritz-Carlton and its addresses, Grand Cayman, it has a rating of 4.5 and not on the local hotel. So these are actually hold those in grand Kim and he can, if you want to verify that, however, I'm not going to specify the container ID. Alright, so I'm actually going to remove clincher ID, but then I do have it as required, so I'm going to remove it in the payload. And what I'll do is me the change in the code itself for the dto. Let's just go over there and make it not required these just for this experiment. And let us try that. So change mid would have the list of photos. They're not referencing any country at the moment. However, they are underneath the country's payload where the contrary ideas three, so let us send. And I'm getting a tool for no content. So let me go and check. So let me get the list of hotels and the see what Kim bug. Alright, here we go. So we have the local hotel going back with an ideal Sullivan and the Ritz-Carlton coming back with an ID of eight. And both of them are parts of country three are key in mind. So you see, that is how you can actually use the put. So put, we'll see, does this thing exist? If not, I will create it. And the only way it knows it exists is if the id value is provided. So when there is no ID value, is going to say, this doesn't have an ID. So I will go ahead and create it. However, because of our constraints that we put on our end point, we are not allowing people to just use the put to create because we do verify that an id value must be present, are a sensible ID value must be present before we move on. So those are the two constraints that you can use to make sure that the put operates how you want it to whoever it's global operation is very versatile. 34. Construct DELETE Endpoint: Welcome back guys. In this lesson, we'll be exploring how we delete data through our API. So I've already actually created this action. If you want again, pause and activated. So I'm giving you a sneak preview has still what it needs to look like, at least initially, the verb is HTTP delete. We need to let it know that it should expect some parameter in the form of ideas and integer we authorize it. This is another one that you probably want to enforce a role for administrator because we're deleting. Otherwise you can just leave it as authorize. And we know that the response codes here would be 4024500. So you can pause and attempted and then we can compare notes. So what I have in this delete hotel axon is a validation to make sure that the ID value makes sense. That's number one. So we do that and then we rejected does a battery request. If it doesn't make sense, then I go on to try to catch his art in logging and returning us status status code, sorry, of 500. But then when it tries operation, what it does is retries the hotel with the id that was passed in. We check if that's hotel exists. Otherwise we once again see bad request and log the error. Otherwise, we go on to delete the hotel and save our changes, then return no contents. So you see there wasn't really much to deleting the hotel. So the same holds true for the country. It's pretty much the same method we have the delete country, we have the same status is if you want to extend the same permissions accordingly. And we go through, we get the ID, we verify that the volume makes sense. And then we try the operation, getting the country, validating that it is not a fake number. And then going ahead and deleting it, if he gets this far, we return a null content of two or four. So what we want to do is test deleting a hotel versus testing deleting a contract. And you're going to see why I'm placing emphasis on those two tests. So with introduction of the delete endpoint, soccer gets a bit more coil full. You see delete being promoted here. And what we're going to do is use postman and attempt to our delete. So you have the end point. You know, we need the ID volume in the URL. We're going to choose our verb as delete. All right? And what I'm going to do is choose a photo that I really don't want, right? So I think this one, this one was just a random tests. You see it's still saying string, string just led the default values are there in the payload example. So I'm going to delete hotel with the ID number five. So in my delete. Request I put in the URL slash x5 and then send. Of course I need to authorize. So let me backtrack a bit and trend get Tolkien their goal. Alright, here's a Tolkien. Grab the talk and John pullover, authorization bearer token. There we go. And we get our no contents. So if I look back at the list, I shouldn't see the hotel with ID five. There it is. It goes four then six. So five is gone. Now that is hole. We would delete a hotel. No, the thing with the countries that the country has hotels. So it's a bit riskier when we delete a country that we're actually going to have to remove the hotels also. So let's see what that looks like. So I'm going to say Country. And looking back, I see that we have to in Cayman have V1 in Bahamas. So let's try and delete the contrary of Bahamas. It only has one hotel, so we'll just, by the bulletin made a sacrifice of dot E1 or E2. We can always add it up later on. So what I'm going to do is see country with the ID3 and go over here. Put that there. Alright, I'd e3 and then send. And we see where getting a no content soul. If I look at the list of countries that we look at the list of countries I shouldn't see. Oh, I deleted K minor. That's fine. So I didn't need that Kamen, so we'll NF2 countries 12, I thought House deleting Bahamas, apologies. So that means none of the hotels that have ID value three should be there so that we send, and there it is. So we have a contract with the ID one country with ID two, country with id1, one, et cetera. So no country with ID3 remains. And that's because in our migration when we created the database. So you can go to the first migration file, I call it the database created. You'll see in the configuration that the constraint on the foreign key was that it said referring auction dot cascade. So cascade means that if you make any change to the parent, meaning country, soil, you have contrary being the parent and hotels are enough conscious. So there the children are at guards. If you make any changes to the contrary accord, it would flicked on the hotel's. So in this case, the genes we're making is that we're deleting the parent required. So on delete, I want to cascade, meaning whatever you do to the parent, replicate that action across the child. So this can actually be changed. Well then you'd have to meet the modification in the context file and then run another migration for it to know that you want to know auction arts or restrict. Meaning. And I usually do I restrict because if there are children records, I don't want to delete the parents. So that means once they're hotels associated with this country, you cannot delete. The country, hasn't restricts wood. Do however, write notes on Cascade, and like you see when you do that peer into record, it's going to cascade across all the hotels. So you have to be careful with that. Make sure that if that configuration obtains in your API, it is deliberate, that is how you want it to work. But this is something that can cause massive data loss if it is, if it goes untethered. 35. Review and Add Changes to GitHub: Alright guys, so we're once again, that's another milestone while we're going to do is shake in our changes. So we added all the missing endpoints for the post PUT and delete requests for both hotels and countries. And the concepts that you've learned along the way can be applied Well as many times as you need them to, as many endpoints as you need to facilitate, you can apply them also. So we just go ahead and go to get changes, add our message. And then what I'm going to do is just commit all and sink. And once that is completed, then you can stick around for the next adventure. 36. Value Added Functions - Section Overview: Hey guys. So we'll be starting a new section of our API development. And really actually this is just a bullet value-added features. We've done quite a bit of work. We already have a functioning API with a nice clean architecture that can be easily extended. However, there are certain things that we want to take advantage of when it comes to dominate core. And these features are, these allowances will enable us to reduce some of the repeated code that we have throughout our application. So let's say for instance, one, we keep on repeating, try, catch. Every time we do an operation, we have the trike yet, so we'll be looking at putting in code to reduce that and handle arrows in a global fashion. Since we really do the same thing almost every time, all things would be looking at will be to reduce our need for checking certain, doing certain checks before we completes an operation. So putting in action filters will also be putting in mechanisms to help speed up the retrieval on processing of data like caching, paging. So we'll be looking at all of these things and we'll start off with implementing paging. So stay tuned. 37. Implement Paging: All right, so let's start looking at paging in this lesson. Null. A little bump groaned us to walk paging is, and why we need it. Paging talks of both segmenting the data that is being returned. So right now what we're doing is we're doing one BigQuery, getting all of the values in a certain table all at once. And while it may look fine because we only have three countries and five hotels. When you deploy this API for international usage. And you're actually storing hotels in 200 countries across the world, you will realize that your data is going to grow exponentially. And then you definitely need to one predictor yourself on your system from too many requests and the burden off serving up that much data all at once to potentially many clients, as well as protecting the clients from having to develop ways internally to segment the data because they're getting about too much all at once. So paging is a nice, effective, and efficient way to segment the data, allowing the client to see, I would like this many records. And then we just return according to what they asked for. It started off with Boltzmann on the screen because what we want from our client is that when they're making that service call, they would pass in parameters to say something like the page size that they would want. So page says would mean how many records. So let's say they say ten. And then they would say and I would like the page number. So that's a page number. So I can either type pretending the link orders, put it down here in the params Chanzeaux page number would be equal to something like one or two. So we need to know implement code to say that if they ask for a page size of ten, that means they wanted ten records. What they ask for page three or something that's not page one. That means it would like the required 30 up until required 40. Right. Something like that. So that we, if they're displaying ten hotels at that time on their PhDs, when they, when they go to the next page, on the next page, they would just increment this and they don't know that we'll get 40 to 50, then 50 to 60, etc. So if we have 500 hotels, at no point would anybody be getting all 500, they wouldn't be getting chunks off 50 or whatever it is that they're asking for. Of course, we can limit the maximum. So what we need to do is start off by creating a new model, someone to call this model request. Params is just a class and it will just be a model or lining. The constraints are the parameter names that there are a lot of passion, right? So before I do anything I wanted to initiate or declare maximum pizza is of 50, so nobody can request more than 50 records at the time. Of course, this is mine or yours. So if you want to limit it to ten, you want to open to a 100. That's entirely up to you. Do what's best for your system. So we're setting that to 50, write null. And then we have another property that we're going to call it page number. And another one, this one is private that we're going to call it beats sides. Alright, so the, these are just default. So I'm seeing that the default page numbering case nano was specified. The default page number will be one and the default page size will be ten, right? But then I'm going to make the page size of public version of the page size, where I'm going to manually say git. And here I'm going to return underscore page size. But then we can also set the value for page size to be equal to. And I wanted to say volume being greater than max bid size. So this is a question. I would just use a ternary operator to see if it is greater than the maximum bid size, then we send the bead size. So that's why I would need there, right. So if they requested more than ten, more than 50 records, so the default is ten, right? There, requested more than 50, then we just send back 50. Otherwise, we send values. So value here is a keyword as you see, highlighted in blue, just like it is for return. So value would be whatever value where sitting here. Alright, so here we just have a default gets set our initializing it to one. So there are no real constraints are on this because we don't know what page they're at. However, or what this one where seeing always return the period size. So when you get the return, what that does is however, when sitting it, if the requested page size is greater than 50 or whatever value you put there, then we return that maximum. Otherwise, then we can go ahead and return that value. Now the next thing I want to do is to modify the controller. So at this point, I'm going to just modify get conscious because that guy said I don't want that any point. Somebody being able to just get all the records at once, that would be problematic for my assisting. So what I'll do is modify, get countries. So this endpoint is no longer does get all countries. What now we are going to see from Query. So will you see in from body the input here? I believe when we're doing the post, you'd see from body. So that requests would have the data in the body, right? So we would have done that. Let me see if I can find any of those with the body. There we go. So that's the from body that it takes it from that whoever From query. We'll look inside of the query string that is being possible for the params. So that's why I called it to request pirates are parameters, right? So from Params where looking for fields that match the names as outlined in our requestModel. Alright, so it's the same kind of concept as the dto write requests firearms. So I'm just going to call these requests firearms Values Award params, that's a keyword. So nowhere looking for our query. Query string, sorry, that we'll have in fields for bids size and the page number. So now the next development will be involving passing that information. Don't get all commands. So remember that's in our units are fork or guitar you seeing, oh, just give back everything anyway, right? So what I'm going to do is pause the query params don't to the gets off and ofcourse that is going to require an override. All right. I don't want to get rid off the origin. I'll get to it may serve some purpose otherwise. So I'm just going to create another one, right? So let's go back over to our Unit 04 units over sort of the generic repository and we have gets all As it is. So what I'm going to do is create brand new declaration. I notice I have this new datatype here I ph list. You'll see more about that in a fuel. So I have task gets all and I'm just getting the includes as well as the request parameters. So I'm not even going to allow them to do the filtering and all of that stuff because we're not really interested in that right now what we are getting all, but we want to facilitate the PGA. So let me just go ahead and include what I can include whoever declared this data type has yet, so we can leave that alone. And since that is knowing the interface, I need to go and update the generic repository so that he can implement it. Alright, so now that it is there, what chord do I put in? So read Andrew them doing everything that I'm doing here. Well, maybe not every single thing because abnormal orderBy, but I'm just going to take that code, paste it, don't hear and the return. Alright, so I'm just going to slowly so we can see exactly what's happening. So there's no expression. I can take all the expression. We do have facilities for the include, but we don't have any order BY so I'll take that one notes. I know what I need to add is a facility to actually well filter our peak exactly what I want from query because this is still just returning everything. So at this point I'm just going to go ahead and take care of this error, which is the IP edge list. And if you look at the suggestions, the library I want is not there. So I'm going to go over to New gets and get its money or these. So manage new AND GET packages. Gautam boroughs. And then I'm going to look for eggs dot paged lists. So this is a very prominent library that helps with paging. So we'll just say expansionist, MVC core. Go ahead and install that and know that it's installed. We can go back and try and take care of those errors. So this is generic repository. No, I can say using x-dot page lists, so I'll go ahead and do that. So making the business this is very possible. But then why do all of that when there's a library, right? So go to the generic. Let's include all missing references. Alright, and then the cool thing though is that don't hear, it's complaining because we have IP is this does return tab or doing to list here. So I page list gives us extension function that allows us to say to page list is sink. And then the two-page nist will take two parameters. It wants a page number and the page size. Where are we going to get that from our request params, alright, so actually I went to even take the null of this, and frankly I'm going to take off the intrudes. Let me just do a little refactor because now I'm thinking about its whenever it getting all night in Pij is when they're paging the data, they probably don't need to include anything about the country or anything else, right? Because they're just listing adults when when you get the details of something, then you probably want to include. So I mean, that's that's up to you. Maybe I'll leave the includes because I could see value in its early of the includes bullets and request firearms. We definitely want that to be mandatory for this version. So let me put this at the front. I think that's why that red line is there. Because anytime you have the apartment, does this study, you have to have the nullable wants to the end. So there we go. So requests params. But to the task that's on query dots as no tracking No.2 ph nist and they were passing query params dot which they sit on first the pH number. So it's important to always look at all the requirements and make sure you're passing the correct volume and then they wanted to page size and yes, I do have somewhere you can get that from. All right. And then I think this areas there because we need to be a C. There we go. So no, we can get a page list of anything that we have in our database and I need to go and correct my repository where I may this not nullable. And of course I need to move it to the front. Alright? So you see as you build on your EPA, tiny G and design made along the way, they're actually required but, you know, once you know what you're doing yeah, near you get on top of it. So let me just do a build and make sure that I haven't missed up anything else I see here. Alright, so they're seeing that gets all. There's none. Ok, so this error is because I'm still using the function get Dawes. So right know we have to get off functions to distinguish between the two of them. What I love to do is pass in exactly the parameters that the 1e No, I want needs, right? So, well actually that's not working because although one still takes more than one, so it's still confused as to which one it is I am dealing with. So what I'm going to do probably should've done this from the start. I'll just change the name and. Do a new one or it someday they tried to be generic. Janet Mock fires. So let me just call this get paged. At least. I think that's clear enough. So I'd generic repository, we do that in a generic repository. We made that change as soon as I find it's there we go, and there we go. So let us take this forest spin. So only done this the countries. And the fact is that we've done it one place and it's that easy to go over to any other controller and made that change because the hard work was already done. Alright, so that's one of the advantages of pumping Clean Architecture and have an error here and not arose us mad, but so does fixed up. Alright, so let's try that again. And when we get to this point and let us try to bring back colon true with bid size 50 and, and page number five, I'm actually going to set a breakpoint here so that we can see the parameters coming in or maybe limb and just put it out and 39. Alright, let's try that. So send, alright, so it's heating the breakpoints. So that means the request was recognized. See for getting the requests params there we get 515. Alright. And they will continue. And we know that we're going to get bug all our countries. The request is for a PID says an abysmal, but that doesn't exist only of two hotels. So well to countries, sorry, so that one is the first indication that this is working. So let's try this again. I want page number one with P, its size two. I will have two countries run by deleted one, right? Let's try that. So when we send, we only get the tool, right. If I requested page one with only one that I'm only getting back one if I requested pH ten, which means skip to the tenth records. So what our library expedient list did was it automatically modified the query with take and skip. Let me just jump over there. So in link or Entity Framework rather, you can actually say something like query. And you can do a tick. So you take this number, right, returns a specified number of contiguous elements, and then you can see where, where it says bypass a number. So that's really what it is doing. So when we send the bid size or let's say a page number ten, it means skip ten, skip ten records or at our skip ten times this number, offering cards and then bring back these mini, something like that, right? So all of that, it sounded confusing, is really not that difficult to write. I'm probably me hates ONE more difficult than it really is what the realities that we didn't even have to do all of that because of our library doing that for us. Words is 2pi is listed, does that automatically, and that is why it takes query parameters maybe. Okay, I kind of go into that class behind it. So that's fine. So yes, so that is how we implement paging. So obviously it, you're probably not seeing the full power of it because I only have very few records. However, if we see that maybe 50 hotels into this database and then we said we want page five and only ten records. Then it would say Give me that. I think my math is off there, but I hope you get the gist. So right, and all we have paging enabled in our API. And once again, this is both yourself and the requesting application. And if these parameters were not provided, then by default, we have told the request params class that devalues should default to page number one and a maximum of 50. 38. Global Error Handling: Hey guys, welcome back. So in this lesson we're going to be talking about global error handling. So I'm starting off in the controller for the countries. And we had mentioned earlier that we'd want to reduce the need to repeat this try-catch. So everytime wearable to do an operation while it is very essential, it becomes repetitive over time because we have four functions where we keep on writing try catch, tried, Dutch try-catch. And for every other phones on it would be important. In. So what we want to do is implement global way to handle exceptions and reduce the need for the repetitive try-catch statements. So what we want to do is standardize what happens when we catch an error. Because when we catch on, we actually do the same thing. The only thing that's sort of dynamic would be the, the part where we see the location, which to me is actually kind of optional and probably don't necessarily have to do the spark. But the point is that the message is relatively the same and we always give that 500 response code. So what we want to do is to have a standard way to represent an aerosol and models. I'm just going to create a new class and I'm going to call it. And then in error we're going to have three fields. So we're going to have status code. We're going to have message I. Then we're going to have a third one where we're providing the message as serialized JSON objects. So for this one we will have Newton JSON, neutron soft, sorry, dot JSON. So that's his whole or error class will look after that. What I wanted to do is extend our startup pipeline, but I'm going to use the service extensions like what we've been doing for the past few times. And I'm going to have a new, and we're calling this new function configure exception handler. And this time is getting the middleware pipeline. So originally there would be get into services this hour gets into application builder. Alright. So in this, we go ahead and we say up dot, Use exception handler. All right, so the dot make core application in and off itself has its own exception on there. So we're kind of doing like an override to see this is really how we want you to operate. So use exception handler and that we need our little Tolkien or lambda looking Tolkien. And then in here we open and close curly braces semi-colon at the end. So inside of this block, and when to say error doctrines had this isn't me adding the costal middleware called null. And I'm going to see async and my Tolkien expert knowledge on when to call context and then my lambda R1. So again, for another object, all right, so what I do is every time I am going to do one of these edges, me shows both the semicolon on the end of the briefs are, the parentheses are out there, so I don't forget it later on. Alright. So then we're going to see, set some. Some constant. I'm setting context dot response.status code to be equal to status codes dot 500. So the same 500 that we return every time there is an error, we're just setting that as a constant so we don't have to type it over and over it. So where was I sorry. So status quotes dot status 500 Internal Server Error. And then I'm setting the content type to be application JSON. Then I'm going to say var context feature is equal two contexts dot features get exception handler feature you may need to import Did I missing data type for this one, so you can go ahead and do that. So what we're going to say no is if the context feature is not equal to null, then we want to say Log dot and then login error. So remember that every time something fails, we actually do that. We have our logger and then we login error where we pass in whatever is wrong, right? So I'm going to say if something went wrong, I'll just copy this basics over here, something went wrong. But instead of name, often get countries. This I'm going to say context feature dot error. So that will kind of give us an indication as to what went wrong, right? So not error, context, feature dot error. Then we go on to say, I'll wait, contexts is bringing us MCT asynchronous programming notes is that this little arrow here is green on the scene that we're seeing a symbol ever awaited anything. So when I say we it, that are, isn't all satisfied at n equals o a or sorry, the async keyword isn't all satisfied. The land goes away. So I'm going to say await context dot response. So we're going to say send back a response to the calling contexts of context here really represents the controller that is passing down the information. Alright? Lucio, that works in a few. So write async, alright? And then we want to say we want a new error. So new error, and I'll just go ahead and initialize this model. There we go. So we want a new error where our status code is going to be equal to the status quo that we just said up here. So I mean, we could have easily said that here, it's fine. But we want that. And we also want our message to be equal to something consistent. So I think here we just said Internal Server. These dragon, I think that that's what we said every single time. So just the message being equal to that very consistent message. And then all of this we want to convert to string. Then we have a semicolon. All right, so let's just review this a little bit. So we are seeing that we want to override our default exception handler. And the way that we want the exception handling to occur is such that when one happens, we write the log and then we generate an error model with the status code and the message. All right, so that would kind of eliminate our need to manually do that every single time. Now after writing that costume middleware code, what we need to do is go over to the startup and I'm going to put that one right underneath the swagger. So we're going to say it up, dot configure exception handler, and that should be it. So what I'm going to do as a proof of concept is removed the tray because try really means do this. So with all the triads willing to attempt to do it, the only real purpose are the game changing aspects of the try catch is that it will see, try this operation and handled the arrows that occur. So if I have global error handling, then I don't need to go ahead and put in anything to handle it manually when something does occur. So I'm going to try and get contraband ID. That's fine. So we're going to run some tests with this as a proof of concept. And what I will also do is, okay, we'll just, we'll just look at how it works. So I'm going to start and I'm going to run our request for API slash countries slash one. And then we are getting country number one, which is Jamaica with the hotel. So everything is working fine. That's what we would expect. Alright? No, It's hard for me to introduce an error otherwise. So what I'll do is introduce the money. Well here in the code what I'll do is throw a new exception because the catch is there to catch an exception. So if I throw an exception myself, then what would happen is that the code would actually stop executing at this point. I never get down there. Now I want to see what response I would get when that exception is thrown. So we're going to go ahead and run that same Postman requests that was just successful and I'll introduce the throw exception. And when we do that, we see that we're getting buck status code and message. And those two fields are the same two fields that we just defined in our error model. Alright, so what is happening here is that the exception handler is actually globally watching for anytime an exception is caught, then it is doing what we asked it to do, which is to log the error and say something went wrong here. So let's see what's in the log and the log m seeing my exception right here. So system except SON System.out Simpson was through and I could have made it more specific exception this data dot. But then if you look down, see the whole pipeline as to where it went. So what happens is that it went to the controller. The controller threw an exception and then they exception handle the hand handler that we overrode, heat our custom code. And then it said, okay, what should I do? Well, the stats are scored is 500, the response type is JSON. I'm going to log the error and then I'm going to write Bach in our response that this has occurred. So that way we can actually safely and confidently, having done that, remove all of the other try catches from anywhere else in the code. Because once again, those try catches were there to make sure that we're handling all the errors gracefully, are as gracefully as possible. So now that we've made it global, you want, you can do is just do as you see me doing, and just go through and take out all the track catches on whatever quantities that you expect to be executed. You just go ahead and execute that. And what you realize is that because of that, the removal of that dependency on the try catch is everywhere in every option. When you are expanding and extending on your abs functionality, your quarterly look much cleaner because then you and your team can thus write the code knowing full well that your exception handling is happening at a global scale. So I've done that with country. You can go ahead and clean up the hotel controller as well as NLL controller that you may have. 39. Implementing API Versioning: Hey guys, welcome back. In this lesson, we'll be talking about versioning our API, though the reason we would want to version are APIs that over time, more functionality will evolve there times when we may change the way our endpoints behave, genes, some verbs are the way the payload is structured, all of those things. But then you don't want to just do that. And then all of your clients one day wake up and realise I'd have to change your entire code base because you implemented a change near API. Versioning the API allows you to kind of run up parallel between the old way of doing things and the new way of doing things. And then eventually you can phase out the lawn dot all the clients have. Of course, after adequate warning and education, our own the new defacto standard that you're introducing. So retinal wants to talk about versioning and our journey is going to start right here in, in new get, where we're going to get the Microsoft is being at core MVC versioning libraries. They can go ahead and search for that and install it. And then after you've done that, we're going to go with the service extensions and we're going to add a new function. And we're calling this one configure versioning. Of course, you know, you can call it whatever you're comfortable with. But right now we're calling it configure versioning. And then inside this function we are going to have code smell to the, so we are seeing services, API versioning. And then we're going to include an option initialization where we're seeing a report API versions, true SWOT report it diversions means that there would be a header in our response is seeing this is the version that you are using. So when our clients talk to the API, we're going to see in the response, yes, you would just heat this API version. We're going to assume the default version when unspecified. So if we have 123 API versions and the client field to specify that they want to use version 13, etcetera. Then we're just going to use a default one which we have gone ahead and specified below. We said the default API version is going to be API version one. So you can go ahead and in 2D any missing or for instance, as usual. And then after you've done all that, we can go over to the startup and we can register OS services. So I'll just put that one below here. Alright. Now what we're going to do is create a new controller. So I'm just going to go to Add. Controller will choose an API and I'll just leave it empty. And then for example sake, I'm going to call this swan country v2. Alright? So country V2 controller. So we have a new controller. And I'm just going to initialize it with some of the things from the original country controller. So I'm just going to copy all of these things. So I'm just, I just want one endpoint just for testing purposes. So the one endpoint that we're dealing with will be to get so go ahead and include any missing referring. Well, actually I'm going to change the way this one accesses data. So instead of it using the unit of work, I'm going to let it implements the DB context directly. So this is. Database context. So of course remember that that's, it's taboo. You don't really want to do that while it will work, it's not best practice to have the APA looking directly at the data. But for this example, I'll just do that so that we have a different return type between the two controllers. So I'm gonna just go ahead and initialize this as quickly as possible. And then once that is done, once that is injected, and this is your V two controller. Alright? So we can specify the route here to be the same thing as the origin. I'll conjure control because remember they'll go to Khan controller, right? So this would be api slash country. However, this by default would be api slash country V2. But what if I said I don't want the controller name. I wanted to be the same endpoint. Now if it's the same endpoint, by default, the API would not know where to go because it's going to see this one with the root and see this one with the same route and it wouldn't know where to go. Now what I can do is specify that this one is API version, and then specify that this one is 2. All right, that should be a string. So API version 2, what would happen though is that the client will need to specify which endpoint it is that they hope to heat. All right, so I'm just gonna do her up and clean this up, put on submit a request parameters in this situation. And I just clean up the rest of it. So I didn't want to bore you with my cleaning up, but this is all that we're doing. We're just seeing get countries. And it's going to return contexts dot countries, which is just going to get the list of quenches into database and return that. All right, so the return type here will be different from the dto return-type of our original endpoint. Alright, so let us take this for a test drive and see how this works. Now if you remember in our configuration we had said that we should assume the default version when unspecified. So what we did here was just to repeat the same call that wheel is due to our endpoints. You just said api slash country. And we're getting Maco, our country's. But then no, if you look in the header section, you'll see that the API supported versions 1 Do Recall that our configuration would have set 1 as our default. Alright, so that is working in, realizes that there are versions on it's returning the result set from the default one. Know how do we get our client to know how to specify which version they want? There are a few ways to do this. Number one, we can requested by a query string so we can see if you want the other one you pass in a query string are via param. Let's just put it in the param APA dash version. And then we would see 2. And then they send, you would see that we get back a 200 OK, and the supportive version is 2. So let me, let me put this into a bit more context so we can visualize it. So we know that we have two controllers. Have controller Quadrature v two, which has the same root as the original ones. I wanted to put breakpoints at their respective functions. And then we're going to see which one gets heat to be estan which requests. So I'm just going to repeat the request for version 2. And then when visual studio lights soap, you see it is hitting the new controller that we set up using the same end point, except we're passing in the query string that we want version two. Alright, so I can continue, it hits the database and it returns the data accordingly, and that's fine. But then if I don't include the param and then do the same requests, notice it's hitting our origins. So that's it. So we can have more than one controllers with the same route, except there are different versions. So that is a quick way for the client to specify that I want version two. If they don't specify, then we're going to send them to version on one. Now another way that we can do this, and I'm just going to stop this right now. Another way that we can specify which one is which version are low. The client is specify which version they want is to modify the root. So I can actually kind of super impose right here in between the word API and the endpoint name. And see that I want you to pass in v colon and the API version. Alright? So when we do that and they're on, I'm going to kind of modify the original endpoint or quests. So initially we had API slash, country slash. We put in the query string to get version 2, but then no, I modify the root, so I should be able to see it to point or right here in the URL, right? So APIs slash 2 slash country. And do I still have the breakpoint CSI dual? So let's see if it gets hit and it does get hit. So you see that's another way that the client can specify which version of the API they want and endpoints. So version 2.0. they specify 2 so it heats the appropriate endpoints. No, there might be a situation where you don't necessarily want to augment the URL because right now all we have to augment our, we are forcing the clients that they have to change their BS URLs, Alright, so they have to see the slash api slash 2 slash endpoint or adapt to Boston as a query string. So another way that we can get the versioning to work and let me just stop the bug is to add a configuration tore Service Extension for versioning, where we see option dot API version or either. And if we just take a little look out what this is doing it to seeing it. It's used to read the API service when specified by clients. All right, so then we can see in new header API version reader. So what is it, a boat, the incoming request that we want to read, right? So are saying we want the header API version reader and we're looking for a header by the name of API version. So this will allow us to one, not only keep our roots the way we had it before, but enable the client to just add a header instead of having to change their entire URL. So let us try that one. So buckskin postman, I'm just going to remove the 2.0. from our URL. And then what I'll do is specify in the header sections you have heterocyclic did API dash version. So that's a new header that's I wanted to pass over 2.2. And then when I send that, we hit our breakpoint in our version 2.0. controller. Alright, so quite a few ways you'll have different phone personalities or different methods of doing things instead of introducing too many breaking changes all in the codebase that everybody's already subscribed to, you can phase in a new one and just call it version, this version that, and have them pass in the header for the appropriate version when needed. No one more thing that's I'm going to show you on this topic is how you can specify that something is deprecated. So in stillness on now and I'm just going to continue using this one because this is experiment. Let's say that a verse on three-point tool. So no version 2 is deprecated or it's no longer the preferred version. So you can actually add to the annotation here that the deprecated value of this API version is true. So what would happen is that when it sends the header across for our response and we can test that here. So this was a previous request, so I'm going to run another requests, hit the breakpoint, continue, but then look at it. This is nosing API deprecated version 2. So no, it's no longer does saying, oh, you're heating the API version is letting you know that this one is no longer the preferred one. Alright, it's probably near end of life, whatever it is. So those are ways that you can actually implement versioning in your API to help control hall YOU fees in your changes as you go along. 40. Implementing Caching: Hey guys, welcome back. In this lesson we'll be exploring implementing caching on our API. Now, caching can significantly improve the performance of the API. Just think about when we have hundreds, maybe thousands of clients subscribing to the API, they're all trying to find all told tells countries and probably even both at the same time. And I can really take a toll on the performance of the API based on the whole infrastructure and a foot, I have to hit the database with every request. So caching will introduce a kind of quick access layer on top of the real data store. And it will significantly reduce how often we have to pull the database. So what we will be implementing is one caching. We'd be looking at implementing an expert experience on mechanism to reduce the whole, often we have to go to the database. We'd be looking at implementing a validation mechanism to reduce the network bandwidth. And at the end of this lesson, we just want an overall feel of caching, why we have it, and how it can be implemented. Now there are three types of caching and I just wanted to give you guys and it's a feared before we get into the whole code matter. So the client cache lives on the browser. So it's a private cache because it's, you know, you need to a single RNA particular client. All right, we have the gateway cache which kind of lives on the server and is a shared cache. So the gateway deployments, I guess, and all the clients hitting the Gateway or at any point in time would be heating that cash. And they, we have our proxy cache, which is also a shared cache. What's it doesn't live on the server, it lives in the network. To start caching or resource, it's pretty simple. What we need to do is add the response cache attributes and set how long the cache should live. Four, right, so over any control, over any end point. And I'll just start off with countries. You know, we'd just experiment between these two. So I'm just going to add the attribute that says response cache. And then duration equals 60. So 60 means if Barnes. Alright, so we're setting up cache-control with a maximum age of 60 seconds. If you look at duration, you see this sets max age in the cache control header. So when, when a client queries for Nieto from the endpoint, there will be a header included that says this is the lifetime of the cash that you are getting are cached data that you are no good. So let's go into debug mode and conduct a quick test. In post model, what you want to do is just make sure that your ascended no cache header option is off. So you can do is go to File Settings and under General does look forward that sitting meets or it's off. Otherwise you can proceed. So we already know that we can look at all the headers coming back. And I'm going to do send. And when we get the response, we see that our cache control header is going back and it has the max age of 60. Alright, now this is really just the header, so we are not actually changing anything just yet. This is just letting the client know that while the data is cached, what's ofcourse we actually need to cache the data. So we're going to have to modify some of our configurations in our startup, which is where I started off. So in our startup dot cs, we're going to add this new service registration in the configure services function. And that I'm just going to put bread here. So services that add response caching. And then after that we need to register our middleware, which I will do right above the routing middleware that says app.use response caching. So you can just go ahead and add those two lines. And then what we're going to do is do another ten. And when I run this request, we are seeing a new header. And this ones is it indicates the number of seconds the object has been in a proxy cache. Alright, so we just thought bubble at the different kinds of caching. So nowhere implementing our proxy cache and see the value here is nine. So if I earn another one and you see it's null 32 seconds into the maximum age of six. So pretty much within the lifetime, if we continue to pull, it, will keep on getting a different value for the ID. So when I do that, you see the age is gone because we exceeded the 60-second soil where I actually went to the database this time, came back and there's no age. But then if I pull it again, now it's telling me that okay, it's ten seconds old. It's 14 seconds old, et cetera. It's NORM.DIST going to go back over to my start off real quickly and we're going to explore whole weekend probably inter implements, sorry, a more global valid because right know, I would have to sit this manually over every option or every endpoint. And then if we change it from 60 to 120 to denote off to go through each one. So what we can do in the startup is added to the config for add controller. So I'll just put in my, my lambda expression. The Tolkien and web R0 and others putting the curly braces will cause, you know, if we have more than one lines to configure, that makes it easier. Well, what I'm going to add is a config to see cash profiles dot add. And we want the 120 seconds duration. So here we can kind of define up cash profile, which then we can use and reuse throughout. So I need, let me see what's I need here. I need a semicolon at the end. Alright, there we go. So config dot cash profiles dot add. We give it any name, you know, within reason. And then new cash profile duration. And you can add other properties to the profile location verb a header Ionia, too complicated. But what we do know is instead of specifying duration here in this header. I can see profile, well, gosh, Profile Name is equal to and then we put that name that we just specified in that slot. So if you wanted to go ahead and test it, I'm not going to test it again because we already get the just off the headers coming back on the age. So no, we've increased it to onto Indian over any end point that we wish to have that cash. And more than likely you'd want to talk about the ones that are reading. The get profiles would be the ones to have that caching profile. You wouldn't necessarily need that over the create and other operations. Alright, so let's talk about a situation where our data might get stale. So as I said, with the cash, it takes like a quick copy of the data layer and it returns that data for as long as we told it to. So in this case it's two minutes. Well, let's extend this to maybe ten minutes. And then the first time the client tries to get data, then it's going to cheat and in, get a cached version on afterwards. But then what if five minutes into this ten minutes or two minutes into this ten minute period, an update actually occurred. So new country got added, right? And then they're still getting stale data for as long as the caches are live. So we don't want that. We don't want that when, when the data changes underneath, they're still getting old data. So on to add to this is some validation. All right, so to do some validation or add headers for validation and experience on checks, we're going to include a new library. And it's going to be this library called Marvin dot cache headers. Alright, so is speed on a core middleware that adds HTTP cache headers to responses. And you see the different headers that cache-control expires, etag and Last-Modified. Alright, so it implements cache, expiration and validation. So you can go ahead and get that. And I'm going to refactor or quarter bit. So in the service extensions on when to add a new function, where we're seeing public static, void configure HTTP cache headers and we know the drill boss in the service collection. And then I'm taking that first line that we added services dot add response gushing as well as services dot add HTTP cache headers. So we're taking those two. And then what we're going to do is just and I reference to the startup, so where I had the original And I'll just add one reference to that function which is going to initialize these two service calls right? After that modification, we're going to add the middleware. So after the US response caching on when to add up dot use HTTP cache headers. And before we do any anymore modifications, just to make sure everything is okay, we're just going to do a quick test and we're going to send a brand new request. And when we look at the list of headers coming back from that requests, look at expires Last-Modified, we have an ETag. Identifies a specific resource versions. So it's just like a little hash that says this is the version of the detail getting very and other things. So we see that we're getting back some new headers along the way, right? You would also notice that the max age is kind of gone back to 60. So yes, it was 12V sets into 12 into, but it's gone up to 60. So we're going to explore how we can customize that max age. And the way we're going to do that is go back to our service extensions and add the following code on the services dot, add HTTP cache headers. So we're going to define a Tolkien, call it experience on opsin lambda arrow. And we are going to say experience on option max, age 65120, whatever it is that we want, we can see the experience on upshot cache location. We'll want it to be private or we want it to be public sermon, but I saw public or private. So let's say we wanted it private. And then the validation option, you see most revalidate equals true, meaning once the betas change, we must go through that process. I get no after doing these modifications, we can actually remove the header from the resource. All right, so let's just do one more test. And we will see that the modification is actually global. Alright, so even without putting the resource R, sorry, the attribute right above the resource, we see that we are still getting about the same headers and I'm just gone on and they live in all of the life of the 1-20. Alright, so the next thing I want to show you are the organics. Things I wanted to show you would be the custom attributes that you can actually add right above the potential endpoint that you want a different setting for us. So yes, we said the global sitting in the startup or sorry, in the service configuration. But then over the endpoint, you can actually override that. So you can just add those missing references. So HTTP cache, expiration and AUC Yolanda different location. You want it to be public and this one should be 60. You can actually override the global settings right here. And then you can tell this one that it doesn't need to revalidate. So just bouncing back to the headers coming but know that we've implemented caching just to go through them once again, this tug actually represents the unique, like I unique hashed to say this is the version of the data that UIC. If, if within the lifespan of the cache, something changes, then this tag is actually going to change and then you would get a new tag. But then for as long as the Datastore does not change, what we're doing is just caching it so that we don't have to hit the database to bring about the same data every time somebody wants. It's at least for two minutes if we'll get one, those are requests. We don't necessarily need to go to the database for the SIM or data. So that is the advantage of adding caching to your API. Of course, on a case by case basis, you may want to customize how particular endpoints serve up the data versus others. You may also not even need caching based on the application or it may not be suitable for the type of operation that you are providing the API for. So this is just another thing that I think it's good for you to know and you can use it, have it in your arsenal for when needed. 41. Rate Limiting and Throttling: Hey guys, welcome back. In this lesson we'll be talking about rate-limiting. Now, rate limiting or throttling as it is also called, is a technique by which we impose certain limits on whole. Often somebody can hit our endpoint and actually get my beta. So of course, if somebody comes and bombards the endpoint as much as we have caching and all these things. The fact is that the endpoint is actually proven to a denial of service or DDoS attack. And what we want to do is kind of put a mechanism in that when we detect too many requests from one source, we can kind of block them and say, hey, here, overdoing it. Outside of the potential DDoS attack, it actually helps us to kind of meter WHO often any one client accesses data and many very popular APIs or their Google. And I'm just going to say Google, but all of those big players with APIs and SDKs, they all have some form of throttling. If you read the requirements and the terms of use of their APIs, they have something in there to see you can request may be 100 per Minitaur, 100 per hour stuff ladder. So today we're going to be setting it up in our API just to get a feel of how it's done. And we'll be using the library is speed.NET Core rates limits. So we can just go ahead and install that. And once that is installed, the next thing that we want to do is go over to a startup and alo or application to use memory cache because it's going to use memory cache to kind of store and keep track of who requested Watts and how many times they've requested it in the timing, right? So again, they'll say services that add memory cache right there in the configure services functioning. Then we have some modifications make to Service Extension. So I have the quote here already. And this method is called configure rate limiting. And we already know that the service collection and what we're doing here is setting up a set of rules so you can just go ahead and copy the code and include any missing references as you go along. So vari, limit rules equals new list, really limit rules. They can have multiple rules. So we have to initialize a new rule object which allows us to specify the particular endpoints. Or in this case I'm seeing Star, meaning every single endpoint is going to adhere to this rule. So based on this structure, I can actually have multiple roots. I can say comma and do a new rule. All right, let me just copy and paste. I can do a new rule, specifies a particular endpoint and then change the limits. So this ones is you're limited to one call per second. Alright? That's kinda short. I mean, we can say ten seconds, one call every ten seconds. I can see one call every ten minutes or 100 cause it's up to you. You can configure it down once again, if you have different rules per endpoint, you can go ahead and add these rules and specify the particular endpoints to which they're applicable. Right now I'm just going to sit a global rule. So I'm just going to say all end points and I'm going to set it to something that is very small so that we can see it in tests, right? So I'm going to see within five seconds you're only allowed one call on any end point. Then we go ahead and we say services dot configure. I will put in the IP read limit options and we just say options, not general rules equals the rate limit rules that we just defined. Outside of that, we need to add these singleton services in the form of I rate limit counter store. And that is going to be associated with memory cache limit counter store. So all of these are just bits of code that I required to support the library that we import this. So a different library might implement it differently. But this is the code required for this particular library, say Candace, hit pause, write them off. At this point, intellisense, we'll be filling them in because you're any of the package. Now afterword don't in-service extensions are just going to head back over to start up and we're going to add these two lines, services dot configure it limiting, which is the method we just configured and the services that add HTTP context accessor. So this gives us access to the actual controller and its inner workings when needed. And then finally, we're going to add the middleware where ethanol routing. So I'm going to put your ads on any caching. We have app.use IP hurried limit and of course include any missing references. Now there have been different response codes used when they're responding to see too many requests. In more recent times, 429 has been used, which literally means too many requests within the past, witnessed platforms using for 20, which means enhance here com and other ones. So let's test this out. So far country I'm going to hit send. And if we observe the headers, we'll see that we get about three new headers, X3, it limits x-ray, it remained limiter meaning and limit reset, right? So it's showing you that the limit is five seconds. You have no more, meaning for a 5 second window and the reset is going to be at this time stamps. So if I hit this multiple times, alright, I'm going to use a different endpoint because I think this one is predicted by caching. So it might not, based on my caching configuration, its not going to violate the throttle. Alright, so I'm going to use the hotel because remember that we set up all of those things on the country and points. So let me go to hotel, which I didn't read them modify as much. So already sends a request and it's showing me the same headers, limits, etcetera, etcetera, fs and another one, what unfolds like lines later. It's okay if I send another one, too many requests, alright, so it says retry after seeing send another request after 1 second, so nothing came back but the message API calls quota exceeded maximum admitted one per five seconds, right? So it's letting me know that I need to try a buck in this amount of time. And when I do, there we go. If I try again, retry after four seconds, try again. And if I keep on doing that instead, adopt valley keeps on changing relative to the number of seconds that I have based on the last request. So that is how we can add throttling. And it automatically once again gives but that for 29 to say too many requests. Alright, and that message, so the client knows that, hey, you're bombarding the APA. Enhance hear calm. 42. Review and Add Changes to GitHub: All right guys. So where it's another milestone where we're just going to review the things that we implemented in this section. And then guitar changes tend to GitHub. So going in order of fault, we did the first one would be paging. So we implemented pinching where we passed in some request parameters into our get's countries. And we also went ahead and set some defaults to say if they don't provide any, then we're going to provide this much information upfront. Otherwise, we give the client the opportunity to say they want this many records starting from this point. There are presented by the number as well as the pH, right? So that's one thing that we implemented. We also implemented global error handling, which allows us to create or write our code without the need for too many try catches. And it comes a little bit neater than it was before, were everytime we're seeing try-catch, try-catch. Alright. Another thing that we did was implement versioning on our API. So we created this controversy to controller just for experimental purposes, where we specify the API version and we explored how we can allow the client to specify which version of the API it is that they want. And I think the last bit of configuration would have them positon as header. Alright, so in our extend services, we put in store for the exception handling and global exception handling to say, you know, when there's an arrow logged and return with that 500 for the versioning, we did say that we want to implement versioning. Reading from the header being passed in with the request, we specify the default API version to be 1. So if money is specified, then it's 1. We also looked at implementing caching. So we can actually just provide the data for up to a certain amount of time before we have to pull the database for the next request. And we also put in validation to make sure that once the underlying data changes, the data kind of refreshes on top in the Kashmir. And last, but by no means least who put in throttling to kind of control how often a particular client based on IP address, at least based on the way we've configured, it, can hit a particular endpoints. So right know the limit is very small, the period is small, but that's just for our experimental purpose in a real situation, probably you can look at other providers like Google and so on. And if your infrastructure is robust enough, you can use their, their values to inform you as to how you can put in throttling What's I leave those example values therefore, no. And what we want to do is check in so we know that we just go over to get changes. And then we put in our message. And that is my message. So when I do this check-in, just go ahead and commit and sink. So everything that's done here. And remember that in the examples I would've done it in one place and encourage you to try it in the other place. But then you can always check the source code and double-check and compare notes. And once all of that is done, we're ready to move on to our next topic. 43. Architecture Changes - Section Overview: Hey guys, welcome back. We've done quite a bit to be developing our AICPA up until this point. And yes, we have a working product TSV have a bunch of features that help us to bring value added experiences when people interact with our API. Lot in this section, we want to discuss certain architectural decisions that we probably need to make. As you can see what we have worked and wants its works. It's good software in terms of you advertised this feature sets and it delivers this feature sets. However, it gets a bit more complicated in the long run where you have to maintain into new wanted to kinda keep certain things separate. When this project girls retinol wheel and they have what tool tables and a few repositories on the units off work and that's fine. But then as the project might expand, because this is the only phase one, as this grows on, we need more data to be stored. We have to do more things. The project is going to get bloated. So right now what we're practicing is what's called all in one architecture. Where when we scuffle a project in Visual Studio, as you see, we get everything we need to actually about working application all in one project. But then a lot of people would probably look at this unfrozen and say, well, you know, everything is 1 proteus and thus not miss practice. And that's true. There are philosophical reasons, or at least tangible and practical reasons that you would want to kind of keep certain things separate. And then that's bringing in the best practice that goes by the name separation of concerns. So yes, we have folders in acting separation of concerns to some extent, but I think he can be refined a bit more. So what we'll be doing in this section is ripping old some of the key elements of the main API, a project, and creating projects where they'll scan live by themselves. So the API will only be API related things, and it will just make reference to other projects that have like data-related things are business logic related things. All right, so that's what we'll be doing for this section. So hang around and we'll have fun as we go along. 44. Setup Data Models Project: All right, So our first project change will be for the data models aren't, so we're going to create a new project. In this solution. We don't want to do that. We're actually the solution go to Add. And we want a new project. And this project is simply going to be a class libraries if you have it to the side, that's fine. If not, you can always just search for our class library. And once you find it, we want a C-Sharp class library. So we select that and I'm going to call this one hotel listing dot data. All right, So we were making it obvious that this is the data project, CMV in, in, in building all these bigger projects are having multiple projects. You probably would want the application layer to have dots, MVC or UI or API. But that's not absolutely necessary and we've already gone down the path of motivating it. So that's fine. You just wanted to make sure that we represent that this new project is dot data representing that it's for our data elements and assets. So with that done, we can hit Next and we want to keep it at dotnet five. Alright, so we could have used on its standard, we could have used any of these, but then everything is dotnet five. So we want to make sure that we stay in dotnet five. Alternatively, we could have used standard there as a bridge between the different dotnet Core versions. Dotnet framework also, what dotnet five works perfectly in this situation. So we just hit Create. And once we have that class library, we get that with class file in there. Now, this activity is going to require a bit of refactoring, which is one of the reasons people just tend to do this from day one to avoid the refactoring process and all that has to happen with regards to that. So you'll see now that we have a new namespace, which means that, well, anything that is in the data folder is safe because it's already going to have that namespace dot data only because it's the hotel listening project and the data folder. Now have a new project that's going to have the same namespace, that's fine. So actually I can just take all of these files. And I'm going to caught, not copy, but caught and click on my new project and I'm going to paste. So in that cotinine piece is finished and I'll just delete this class one Nazis, I don't need it, right? When that is done, you'll see that all of the references are still there, but then we're getting some red lines because with API user there is no library reference that let's know what identity user is. So that's another thing. When we're breaking out into multiple projects, we have to make sure that we represent the different elements are libraries or other that each component may be dependent on. So quite frankly, this new project is oblivious to anything that existed in the old one and that's fine. So if I jump over to the database contexts and give it a few seconds, you see it's starting to light up with all of the errors from the missing libraries. Now, easy way to go around this control dots. And then I can just go ahead and install the missing package. So I would need both actual load need. I need an entity for Entity Framework Core. Know I have the local version, which in my case is 5.02. You might have a different version. I can also find and install, but I'll just stick to the local version. And there we go. All of those errors are no solved. But then I still have this issue here with the hole to listen, dot configurations, not entities. Now those configurations exist here in this folder, and these are really entity configurations. And I had included mapper initializer in that configuration. So what I'm going to do is cut the entities folder from the configurations folder and then go down to the data project. Click Add. I'm going to add a new configurations folder. And the thing is that we use these configuration files solely for seeding. What the reality is that these configurations can be used for anything that you want to be unique about that entity when it's being created. Well, if I go in depth in that, in my Entity Framework course, but I'll keep it light enough for this one. And in this configurations folder, I'm just going to paste entities folder that we just caught. So now all of our entity configurations are sitting where the entities are or the models are. We just need to let them know their new namespace, which is hotel listing, dot data, dot configurations, the US entities. So we only have a few. I'm just going to do that update manually. In a case where you have more, you probably want to do like our control, find and update them more quickly. But as you can see, it's happening quite seamlessly at that point. And then in the database context note to solve this using statement, I just let it know I'm using hotel is in dot data configurations entities and there we go, those errors are now gone. So at this point, I have a few more areas that I'm just going to click through to see what else is complaining as we go along. So EPA users don't. And a nice keyboard shortcut when you want to clean up these files, you have all of these unnecessary using statements. You can just do Control key and E as an egg. And you see that it kind of cleans up the files and removes unnecessary using statements. All right, so let me just click through and see what else is completable missing references. All right, so no, In my API project, it's complaining that it cannot find that dot data namespace and it can't find the database context, of course. So I can remove this data folder. It no longer, no longer as an irrelevance. Fine. What do you know the whole project for those data files. So I can let the AICPA ennoble the new project by going to dependencies, adding project for reference, and then clicking hotel listing dot data. When I click Okay, and then do a build. You'll see that I have a successful build with both projects succeeding in the build, I have no more errors. And you see that was a nice, simple enough procedure. It's always good to do this, like I said, these kinds of refactoring activities when the project is young. But I will say it's not that you should always do this. Sometimes your context determines what you need to do. So for a very small API project, he probably wouldn't need to break out into 34 different projects just because you want your models to be separate. But then when you see that this budget might grow and blossom into something more than you wanted that consideration early Old. 45. Setup Application Core Project: All right, so we've successfully separated our data related assets from the application projects, and that's good so far. All right, Now we're going to move on to the next phase of our little operation and not want to do is kinda set up our application core. This would hose maybe like a business logic and any application specific configurations. It, it can go by many different names. So the name I'm giving you is more like a suggested Nim. That kind of suggests what the layer is a boat or the project is a boat. But I'm not necessarily saying that this is what it must be called all the time. So you may see other people with similarly named projects with various assets and configuration files being stored in there as well as maybe business logic and the details and all of those things. So let us get started with that one. So I'm just going to right-click the solution once again. And we're going to add another project which is going to be of a similar nature, a class library. And it's going to be called Hotel listing dots. We can call it application. Core would just call it core. I'll just work with core where I just call it Total listing dot core. Click Next. And this one is also going to be a dotnet five project. And that creates, now as usual, we start off with the default class one file, which we can just go ahead and delete. Now in setup for core, I'm going to start off by taking all the details. So all of the details that are currently in the hotel listing project, I'm going to put them inside of the core project. So I'm going to create a folder where my details will live from no on. All right? And I'm going to cut all of these oats and place them inside. So actually, I'm not cutting all of them. And I'll show you why. These are details and these are literally models. So anything that's a detail meaning it looks like the data class and we had a number of them for different reasons. I'm going to actually keep them are sorry, I'm going to take those specifically. So I'm not taking error, I'm not taking requests param because those were kind of specific to the API level, not the not that the BTO level, right? So I'm going to cut those and then paste those inside the details folder. Of course, I went off to fix some references here, so no, my namespace here is hotel listing. Dots. It is no dots, core, sorry, dots. Details. No longer models. So that is our new namespace for details. So there was going to use that that new namespace across them all. So they all know where they live. All right? And everybody should be able to see everybody know that they're all in the same namespace. All those areas should disappear between the files. And you'll notice that when I copy and paste, certain things just get added quite quickly. So I've enabled a feature in Visual Studio. If you go to Tools, Options, then text editor, C-sharp advanced, you will see an option here that says Add missing using directives on p. So when you're cutting and BCR copy and pasting code itself will actually just try and put in all the using statements that might be missing, right? So that could speed up the process of moving code around in the future. So now that we have moved all of our details, if I do a build, I know I'm going to be in for a bunch of errors because anything that relied on the details will no longer nowhere details are and that's fine. That's part the other factor. I also want to move over my services folder, so I'm just going to copy this and paste it in the application core, right? And then once again, we have to update this namespace. So this one is no hotel listing dot core, dot services. It would be the same thing for its interface. So we can just meet that update quickly. Now, you see all of those herbs because it doesn't know where to fence all of these identity related options on these extension configurations. And some of those libraries just aren't in this project. This moment. Well, before I start adding, adding, adding the project references, I just want to move over all of the key files first. So the next one are ones would be the repository stuff. So I repository and repository. We can cut those. And based over here. And You know, at this point some people would actually just merge these folders are probably just have one folder that says repository and then in there have both interfaces and the contracts and the implementations. You don't necessarily have to do that, it's up to you. But I went to keep the folder structure. And this is now going to live dot core I repository. And what I'm going to do is just copy that hotel, the core 100 please. All of these references through and through our projects with the new namespace. So at end of this process, everybody knows that they have a new home. But once again, some of the Predict references are still hold off for a walk. That's fine. We'll get there eventually. All right. So one other thing that I'm going to want to move is this service extensions dot CSS file. So in the startup file we had all of these service extensions on, so on. As at this point, they all live inside the AICPA project. But I don't necessarily want them inside the API products. So I'm going to take this service extensions 0 and I'm going to place it inside of the core. And once again, I am going to let it know that it is told to listing dot. All right? Now what you're going to see with this kind of movement is that all of these references to all of these libraries will no longer be specifically in the API project. They will know live inside the core project. And then the API Bridget will just make a reference to the core project. So when we're adding a third party libraries, maybe later on I want to add a mailing system. All of those things, we would just keep on adding to the core because the core is going to be lead immediately between the API and the actual functionality that interacts with third party applications, right? So that's why they're repositories here because it's interacts with the database or services, is here directly with the API or the identity service. Rather, the detail is there because it interacts with the third party people are. So anything that is kinda third party related would kind of go inside of the core area. And if in database related goes inside the data project. And then anything that is the application itself was into our API project. Now, just notice that we still have this some cool controller and the model. So I'm actually just going to delete those two because we really don't need them. But there were good for informational purposes initially, at least, right? So I think our projects are looking good apart from the arrows obviously, but this is what our solution is starting to look like. And if you look here, it looks much more compact. It's much easier to see exactly what you need when you need it. If you're not doing anything there, you can always go to the core and go ahead and apply any modifications to any of these. And then you can always just extend the list of projects accordingly, sorry, entities according to read. So let us add some of the dependencies that are missing in the API project. I'm going to add the project reference to the core project. And in the core project and when to add the missing reference to the data project. Now with that project reference being made, if we go back to any of our controllers or anything, I don't want someone to start off with is a clean up. I'm just going to do Control key, sorry, get rid of all the missing unused using statements. And then I can use my control dot to include the new references, right? So for all of these narrow lines, I can just do Control dot-dot-dot the using statements. And to keep it simple for this particular activity, what I want to do is just make sure that I anything that can be solved with a control. That's what I'm want to focus on her at all. So if I go to Control key, get rid of the on US statements and then Control dots to add the missing ones. And then once I see that I have no more errors, move on. If I still love Arizona icon, solve it using the suggestions from the Visual Studio, then I'll leave it alone. All right, so I'm going to leave that one alone, right? No. What happens is that you're going to be seeing arrows because certain libraries are missing. We're going to be taking care of the missing libraries in the next. So I just wanted to keep this one kind of tight and focused on getting these projects in. Project reference is up and running. All right, so go ahead and include those missing using statements. And once all of that is done, I think most of our errors that would be lift will be inside of our core projects and more specific value instead of the service extensions inside of the repository also. Alright, so when we come back, we'll do a final cleanup and then just run a test to make sure that everything is still ticking along as expected. 46. Clean up and Test: All right, guys, so now we need to clean up all of the errors that we left from our previous activity. What I have open right now is the hotel listing application. Sorry, the hotel listing project files. All you have to do is click on the project file. Just one click and it will show you all of the packages that are being referenced inside of that file. No simple enough way to get these projects over to the core project is to copy the item group. Actually, I'm going to do a cut because these are more like third party libraries. The only ones that would probably need to keep over here would be like the auto mapper because we still have the automatic configuration here. And even then. I think we could move this. Come to think of it, so I'm going to move that I know I said it was a clean up. No, I'm actually doing another movements. I'm going to cut configurations and be down in the court once again. Third party related things you want to put in that folder there. And I'm not necessarily saying that this has to be this is just three different projects, three different layers, so to speak. Some persons would actually have the core different from the business logic. But then this isn't really our business model because everything is generic, and it's so you need to work within. If you had specific repositories that were doing like specific operations all the time, then you'd probably want to have another project that is storing that kind of stuff, right? So it's not necessarily that it has to be three projects. If you do my course on Clean Architecture, you see that you can end up with five or six different projects. And and what we call only on architecture, but we're not going into all of that in this particular activity. So no, that I've moved this upper initial laser over. We need to, of course, set up our new namespace. I just control key to clean up that file. And of course, we have a bunch of areas, which is why we're here. So in this project for the API, I'm going to take this entire item group section and this is a much quicker way of getting all of these references into other projects than to go into new get and get them one by one like we did initially, right? So I'm just going to put them. And then go down to the core and I'm going to pierce them, so I'm just going to put them right above that item group that's there, and then I'm going to save this and just build. And after the build, I still have a bunch of errors, but what is happening is that it is restoring and registering all of these references. So that's fine. We can go through and solve all of those issues. So if I go over and jump back into the API project, you see, yes, we have a bunch of errors in this is the start of us. So we're in the start of that case file of our API project first action control key. And if you don't like the keyboard shortcut, you can actually just press that it's a brush it on there. I had just runs that clean up for, you know, all of these are headlines refer to the service extensions that are now missing from the API project. So if I control that and then introduce a suggestion, it adds the using statement for the core project. And look at that. Most of them go away. Now this one is saying it wants to add autumn paper, and it can't find the mapper initialize laser. Before I tackle that one, though, because they're going to do something special. With that, let me just go ahead and add the other missing using references for the units of work and our eye off manager. And with all of that done, we have fixed most, if not all, of the errors. Okay? OK. This is because there are still errors in the target for the fix. So that's fine. Let's just focus on the auto mapper. No, what I can do is actually create an extension method that registers automatically because the initialize laser is no longer in our API projects, so we don't have to worry about that. What we're going to do is rewrite this bit of code and you'll see why in a few. For no, let us go ahead and add the missing using statements for the other two lines. And this error is there, probably because there are still unsolved mysteries with the files being referenced. So that's fine. So let's focus on the autumn upper. So what I'm going to do is add a service extension method that will configure autumn upper right. So we we have a few written already. I'm just going to take one and kind of duplicate it, and this one is going to see configure auto mapper. And inside of this, we're just going to see something like services that add autumn upper and assembly that get assembly. So there are situations where you might have multiple mapping configurations. And don't get me wrong, we could have used the same type of map or initialize our code coming from our Start-Up file, I could have reused this exact syntax. Right. That would work. That's fine, because as long as it knows where the upper initialize laser is, it would be OK with that, as you can see. But like I was explaining, there are times when you might have multiple upper initial risers, maybe have different endpoints or you have so many details and entities that you might end up having different upper initial risers with different configurations for different situations, whatever it might end up being if the system grows to that size, you can use this general expression where reflections will actually just go out and find any file that matches what Autumn Upper is looking for, which would be my upper initialize or inheriting from autumn upper right. So either one of these lines would work perfectly here. But my point is that we have to move it out and put it here, because that's where the upper initialize in our lives. So in the start that CSV file, I can now see configure. Autumn Upper. And that would be a case closed. All right. So I think I'm going to go ahead with the more generic approach where we just say get executing assembly and ad autumn up accordingly. All right. So I just scrolled up a bit and I'm seeing the exception handler and that error model, we didn't move it. So yes, I made the decision not to move because I thought it would have been better in the API. Clearly, it's needed over in the course, so that's no problem. I'll just take that error object and we can. I don't want to put it in the details. Well, it's not a little. So I'm going to create a new folder called Model CSC that I'm kind of being specific or at least as best as I can be with where I put what. Because at the end of the day, separation of concerns does make your project grow. But then it helps you to be more targeted with where you're putting what's and what you're naming your files and folders, right? So here I have the AirDots case, and I just let it know that it now lives inside of the Dot Core Dot Models folder, and that should take care of the error that we're seeing in that file. All right. Once again, I just need to do my cleanup. Control key. Get rid of anything that is not being used and are not needed and jumping over to the earliest. We see that we're down from 50+ arrows to No. 40 plus. That's fine. So let's jump over to the mapper and we see here that it is complaining about the. Profiles, if I control that I'm using Autumn Upper, that takes care of one thing, if I control that and add the using statements or the details that takes care of another thing. And just like that, all the arrows are gone. And then that list is reduced by about 15. So now if we jump over to the next troublesome file I unit tough work. It doesn't know where it is. So we can just go ahead and add that using statement and anything that we can't find, we just control that right? So it can't find the database context. That's all. OK, there it is. Using hotel listing data. No problem. And that should take care of all of the other files that it cannot find. All right. And then we have some arrows, but the control that won't solve those. So that means I need to solve what's in those files. So you see some of these, even though there are lots of errors, a lot of them are contained in one file. So by fixing IE using statements or something where getting rid of the errors very quickly. So let's jump over to the other files. This is the author manager just needs using statement for that and just a control key to clean up. Anything else? If I jump over to ISPmanager, so you'll notice that these are the blue markers here on the margins. So those allow me to jump over to the files that are being inherited or that I file is inheriting from right. So I can always just say, OK, what files inherit from ISPmanager? And it will just never get me there. So to enable that one? And I've shown people this one, and it didn't work for some. It worked for some. But you can just go back to options text editor C-sharp Advance, and at the very end you'll see inheritance margin, which is experimental. So if it doesn't work, don't sue me, please. But generally speaking, it should work like how you see it be being used for me here so I can just jump over to ispmanager and fix that using statement and control Katie to get rid of the errors and the unnecessary ones. All right. And if I go back to the list, that takes care of quite a few if I jump over here. Control key here. So request firearms is actually needed by the repository also. So that means at this point, I don't have any use for the models folder. So I'm going to take requests params placed inside of models in our core project let it, nor its new home, which is Dot Core Dot models. All right. And I'm just going to remove this no unnecessary folder from our project. All right. So where was that error? So we're fixing this error. Let me just jump back over and I think we're in the generic repository. But while I'm here, let me just to control it. You get rid of some errors and then I can use what I can use inheritance margin because there is an error in the generic repository. So when I jump over to a generic repository, I can fix this using statement for quest firearms. And once that is fixed, then I should be able to go back to the generic repository and see an error free file. If not, let me just control that at the using statement. And that's fine. And then of the using statement for West firearms. That's fine, so I mean, you might not be going through the same errors in the same order that I am just because I just I just got up with myself, I realize I might be moving a bit quickly, but I hope you're appreciating the thought process behind the reflecting on what needs to be fixed along the way. All right. So you can always just keep on ticking at earliest. And as you are, you using statements as your fix namespaces, you'll notice that that early just reduces our reduces and reduces. So here I'm down to six errors. We started off at 50 plus I'm down to six. So just adding the using statement for that error model that reduces us to five and then control it to clean this file up and then adding the using for quest firearms. And we're almost there, almost home free. There we go. And just control key. Seeing that one up and there we go, error free, let me do a build. And voila! So now we have successfully build built projects. All right. So let us take it for a spin because yes, this looks nice. Our API project is now much slimmer than it was when we started. But does it still work? So let's take that for a spin. All right. So it's booting up, and that is a good sign. All right. So let's try something simple enough. I'm going to try and do our registration right. So try it out and I'm going to register as user il1r2 example become my password is a complicated enough password as we know and we have tested, and I want the rule user. Everything else, I just leave and then I click execute, and then I'm getting a total response, which suggests that it was successful. So that means everything that we have configured is still working right. All we did was move the files around, make our project a little cleaner and a bit easier to maintain and even test. So I'm not going to talk much on unit testing, but one of the major reasons people tend to separate their files that is to increase the stability of the code one and to make it a bit more modular. So it's easier to test and see what is being tested if you want more on unit testing. I have a course test driven development speed on it core that you can do to see whole unit testing works in a situation similar to this. So with all of that done in the next lesson, we're just going to review all the changes that we made, the thought process behind these changes. And if it's really necessary or not. 47. Review Modifications and Benefits: All right guys, welcome back. In this lesson, we're just going to review all of the changes that we made to our API project. So once again, what we started off with is generally referred to as an all in one architecture because in one project, we had Database Connectivity, we had business logic, we had everything, alright, called the configurations, third-party references, et cetera. Now as we've seen and tested and proven, everything works as expected. So what we have done here is not necessarily to enhance the functionality. Because we had functionality. What we've done is to enhance maybe readability, maintainability, and just the overall layout off the project. So that in the long run we know where we need to go to find why. There are many aspects that you can add to an API project in terms of just the architecture off the project. And I go through a lot of those in my course on solid architectural with sodded entity and architecture in ASP.net Core. So you can check out that course if you want to see just how much you thought process get really go into building out. And APIs architecture. I did mention testing. Testing is a bit more possible when you kind of take this approach and separate everything. So you can check out my course on unit testing also. But my point is that at this point we have changed the layout of the files, but we have not taken away from are added to the general functionality. So functionality can be accomplished through all in one architecture, like we see in bullet. We did this to increase the maintainability and readability of our files. So let us review everything that we did from start to finish. The first thing that we did was to create this data project. And in this data projects we put in all our configurations for different entities as well as all of the entities as well as the context. We could have further separated these unmade a folder just for the entities. The way you lay it out is based on air contexts. Hope you find it most readable to you. Or whole year project. Teammates are lead, we'll find it most unreadable. Everybody has a different standards. I'm not trying to be prescriptive with my suggestions, right? So by separating the data objects from the API itself, we took out all of the concerns of both database related assets from the API, from the application itself, right? And then in order for it to still know where to go and look for the data related objects. We just simply put in a project reference to the data project. All right, along with that came any other third party reference like the one's identity core and so on. So anytime you are putting in something that was, anytime you're putting in something that has a third party reference, of course, the project itself needs to know what those third-party references are. The second thing that we did was to create the obligation on core and all the general thinking behind the core is that it needs to interact with anything that's his third party. So once you have something that's third party or needs to mediate with a third party library, our system, you can think about putting it in the core. So in contexts, we have the mapper initializer, which is for autumn opera. That's a third party library. That's the deal is the third part is we'll use that to transfer data. We have the repositories, these interact with the data layer soleus. They're interacting with the database, which is third party. We put that there. That could also double as business logic, right? If we're using custom repositories along the way, we have models here because certain operations require these models. And then we have the services which interacts with the identity in this situation. Then I also put this service extensions in the core project because here's where we're registering all of the third-party libraries that we don't want to meet direct references to in our API. So let me IT director for instance, to them in the core project. And then we setup our methods so that we can do the registration. That's fine. And then we put all of that in the core null for the API based on the way we built it. So based on the way it was constructed, some people would actually have it that the API and never sees the data layer itself, right? But because of all we built our controllers and we use the unit of work, It's kind of difficult to do that because we have to make her a friend, Derek, or for instance, some of the entities. So when you talk about thin controllers, which also louis threw in my clean architecture course, I'm not trying to mark it's there anything as I'm just making you know, that you can go there and see it. But we talk about thin controllers where we're doing much less. But that's better understood when you have a foundation that looks more like this. So you understand why you would make certain decisions. So it's good to do this course and then do that one. So you can get that kind of upward trajectory in terms of thinking and understanding how APIs are developed. But my point is that we have to make reference to the data project and the core project from the API in order to facilitate the references that are needed to our unit of where to our entities. And in our startup dot cs, all of our custom registration services that are being gone figured. All right, so all of those little things do play a huge part in all of this coming together. And pretty much that's all that we are going to be doing to refactor this hotel listing API. Once again, we took one project, split it out into three, have more files, probably have more folders, but guess what? In the long run, it will be far more readable and easier to maintain it. Now before we proceed to checking this in, there is one more adjustment that needs to be made. And while giving you that monologue, Justin, I noticed it. So we have this Migrations folder which included me. I don't know why I overlooked it so much, but this Migrations folder should not be here. It should be in our data project because it represents all the database migrations, right? So I'm going to quote it and I'm going to paste it inside of data. And just for consistency purposes, I'm going to make sure that each one of these has the dot in it. Namespace, right? So we can, there's a little through open each one and give it dot data. As well as for the snapshot, you want to give it data. And all while we're still in snaps, I would see that we have this airable to use identity columns. So I think that is our reference or with our project toes, we're only including the ASP NET Core identity Entity Framework Core. But if I'm not mistaken, we also need the SQL Server. So remember that we took this entire item group from our API project. So I definitely need this library. I'll just copy it's because I'm not sure, Depending on it, but I will copy it and paste it in the data project. And when I come back here after it does its little checks and balances, or if I force a build, that error should disappear. And I should know have error-free projects, okay, I still have some errors. And these errors are appearing in the auto-generated files that correspond with the with the migrations. So let me see if giving those the namespace would solve the error and it does of there. So at this point though, because we're just recapping on unwrapping opened up here giving another activity. But I'm just going to point out your options at this point. You can like, oh, we only have maybe four or five migration files you can go through and do all of that and update the namespaces. You could also just remove the migrations because migrations are really just the history of the changes of the database. But then if the database is where you want it to be, the next migration that you're on. If if everything is devoid of migrations, would have the latest version of the database. Now this is all in dev. I'm not necessarily saying that this is why you should do, but once again, context is everything where developing something here, we have delivered Seoul, lets us run an experiment and I'm going to do everything here nor Fuller's. No, I'm not covering up anything. I want us to see exactly how this would work from scratch, right? So once I just did was move over the Migrations folder because the migration shouldn't be in the APA, that's fine. But if I take migrations and click Delete, delete, remove that Migrations folder, and then I go to my Package Manager console. No, I can't do any migrations here because I need the tools. So let me just go over. So I'm just showing you all of what we need. We need tools that we need the design. Is there another library that I need? I don't think so, Right? No. And I might just need the Entity Framework Core if I don't already have it. So let me just dig these two libraries. But over in the data project. And I'm going to just jump back over. And I'm also going to take Entity Framework Core and put in this project. So when I'm running migrations null in the package manage cons, Package Manager console. I need to make sure that my default project is set to the data project because that's where the context lives, right? So if I say add hyphen migration at this point, sorry, name, it would be fresh. My agrees shot. All right. And I'm getting an error because I'm still missing the design package. That's what I really wanted. All right, so let's just add that design packets. So this, I don't want to use NuGet and search for Microsoft dot Entity Framework Core Design. And there we go. So this go ahead and install it. Now you see that the version here is much higher than the version I'm using. That's fine. I am going to drop it down to the version on because I want to keep my project consistent. What you make sure that you're using the version that you have art. So install. And once that is done, I'm going to save say c know that design is added, right? So I wanted to go back and it's all good because I messed up the ad migration commands. So fresh migration, press Enter. All right, so the error is repeating. Oh, I'm so sorry. So this packet should also be in the startup. The startup project is the API projects. I'm just going to jump up there. And I'm just doing this quickly. So I'm just going to create an item group mode, TIM group. And in that item group, I'm just putting in that design that I just took from the project. Alright, so let us try that again. So you see, I said I'm going to do this from scratch so that you can see the process, see the arrows, and know what to expect. Now you see, I have a successful migration. And if we look through this one in, if we're looking at a photo, we see that we only have one migration file. All right, and it goes to their cards namespace, and the autogenerated want goes to the current namespace, that's fine. But if we scroll through, we would actually be able to see every single thing that has been done up until this point. The R, Once I should see is that let us say you had a lot of ADA column, remove a column, change our column, Do this, do that to the tables along the way, which is a standard parts of development. But you ended up with 20 migration files. So we add for migration fuzzy could have ended up with 20 because trial and error changing here and there. So the point is that if you actually remove all the migration PFAS and do a fresh migration, it will take a look at what the data looks like, know what the database structure is. No. And that migration file you get with have all of the changes as at that point. So you would easily condensed 50, 60 migration files into one migration file that just gives you the latest version of the database in one goal. So that's probably something you would want to consider also going forward. Of course, having the migration in increments also helps you to roll back if necessary. So you can you can gauge what you need to do. All right. But I just wanted to demonstrate why we would move the migration file all it off the web project and what the potential ramifications are. So with all of that done, I think I'm actually done with this lesson at this point. We have refactored our project and know everything is where it, our Everything know as a new home according to the role it plays in our application. 48. Configure Hosting Environment - IIS and SQL Server: Hey guys, welcome back. In this lesson, we'll start setting up our environment for local deployment of our API. And notice, when we say local deployment, this could easily be your personal machines. So in my situation, I'll be deploying it on my personal machine. But it could also be on a company mushy in our server somewhere that this API needs to serve across the network. And it could potentially even be. So the Internet's whatever the situation be, teaching, you, are showing you critical steps towards prepping this machine so that it can host your API. So our journey starts off here where we have to download the.net favor untimed Lord of the SDK, which we've been using for development. But we want to make sure we have the runtime and we can just get that hosting bundle for Windows. So when you do that, you launch your installer. And then you go ahead and go through security checkpoints. And the ones that is done, you can close that. And then we know we're going to move on to setting up, I guess, or Internet information services. So what we want to do is, I'd say again, does go to your start menu and see the feature. And then you want to click turn Windows features on our off. So ones that they selected, this little box will pop up and you want to make sure that you select Internet information services. Once you do that, you're going to get that square. That square means that it's not everything that is ticked, which is fine. You don't need every single feature. I'm going to just show you the ones that I have currently installed and then he can just go through and make sure that those are also ticked on your side. So I have the management console and then I have these libraries for application development features. So you can make sure that you tick these off. Maybe you don't need all of them, but it works for me with these, I would recommend that you make sure you have those. And then for HTTP features, you can go ahead and take those health and diagnostics once I, well, that section is actually optional, but I recommend that you get the HTTP logging section. Then performance features, basic authentication and the others. So once you have those, you can click OK and then it may take a while to install. I already helped them so I don't need to wait for them to install, but once they finished installing, then you can resume this video. So once you're sure that you have, as that process is finished, to make sure you have S, you can just go to your start menu and type in S, and then you'll see it pop up. And then when you launch, you'll get this console showing you your server and all of the sites that you have currently listed under there. To make sure that it's working, you can actually just click on Default websites and go to Burroughs. And then it will show you this page which shows you that you are now seeing your server. Now another essential part of setting up your local environment will be to make sure that your database server is up installed and running. So when we talk about the database server, we have a few options in an enterprise setting, you probably already have it or you should have it. You can check with your system administrator whatever you need to do. But you just go ahead and make sure you have SQL Server on a personal level. If you don't already have it, you have to options. You have either developer or express. So expresses very free. No licensing required at all. And what then it has some limitations on a personal level expresses fine. Developer gives you far more features and it's actually full powered. So it's a much bigger download and a much bigger task than having it installed gives access to many more features. For this deployment, you probably can get away with Express, but then maybe if you're thinking about longevity, you probably just want to get developers so you have everything you need so you can go ahead and download that. The installation is pretty straight forward and at the end of it you'll be prompted to install the management studio. And just in case you missed that step, you can always just Google SMS, which is short for SQL Server Management Studio. And once you go through that, you can always just don't load the management studio through this medium also, which is also a straightforward installation. So to launch the management studio, after it's installed and connect to your database server, you can go ahead and click the icon and you'll see this splash launching screen. And to connect to the server, you don't have to put in a server name. So I have two servers running on, a few servers running on my machine or I know I have SQL Express, so I do have an instance of SQL Express, but I also have an instance of the developer. So to get to SQL expression against say dot backslash SQL Express, that not really means local host also. Alright, and if you went with developer, then you just need localhost. So you wouldn't need any slash anything else. So I'm going to use developer, say if I say localhost and it will connect, and I think I've a few databases, not too many. So we can proceed now before we move to the next step, I just want to encourage you make sure that you have admin access or even if you don't have administrative access, if you're in an enterprise setting where you're not in a position to be the administrator, that you at least have enough access or you are working with somebody who has the access to carry out some of the actions here. So a lot of the problems that people and Colin's are when doing these kind of deployments outside of probably missing oughta library and not installing something. The next biggest issue is usually permissions and author authorizations, right? So it does make sure that you're working with somebody that is the case who has enough permissions to go around and the potential roadblocks. And if you're on air personal machine just are a machine that is yours to manage. Just make sure that you have administrative rights. 49. Publish Application to IIS and SQL Server: Alright guys, so after setting up your environment and sure you visited that everything works. Now what we want to do is actually published the site to our, I know before we do that, we have a few steps that we have to complete. And one code change in particular that I want to do is regarding the swagger UI. So in the start-up page where we have app.use swagger UI, I wanted to kind of change hold this endpoint is generated. And the reason is that I have witnessed that wants it is publish the path rules kind of chains. So what want to do is make it look something more like this were used server UA or seed, lambda Tolkien. What then we have the curly braces making it an object. And we're just going to kind of qualify the base path of MIT to see string dot is molar whitespace c dot, root, prefix. All right, and then we're going to say dot, dot, dot. So what happens is that when the root prefix changes relative to if it's in development like it is now, r. If it's published, the, the path needs to look a little bit different. So we're doing is just seeing either put one dot, two dots, and then we're just going to prepend that to our existing path, which was there before, and hotel listing API. Alright, so you can go ahead and make that quick change. And just to double check that it still works again around. And we're still seeing our Sagar API documentation. And you would also notice that the URL has dot-dot. When we click it, we get this. So when we go to that link might look slightly differently, which is I went through all of what we just did. Alright? So not only confirm that he's working on other very important thing that we want to do is create the database. So in our database server, so whether you're using SQL Express or you're using developer, you can just go to that particular instance that you hope to host the API's database, sorry, on. And then you just want to create a new database. So you want that needs to be present for when we do our migrations, right? So because I don't want any type was I'm just going to double-click the database name from the, from the hosts, from the app setting, sorry, and then go ahead and use that name to create the database. And then you can go ahead and confirm that the database is there. It's empty, right? Nodal or too much about it. But this is the initial deployment, right? So what we'll want to do is publish. So we can go ahead and right-click our projects. We see Publish, click that, and then we can choose our target. So we have quite a few options here. You can publish to a 0, which we can look at later on to Docker folder, FTP. This would come in handy if you're hosting like on a GoDaddy or one of those or you hafta FTP to the server that it will be hosted on. Or you can go directly to iOS or if you have other profiles, you can just import a profile. So I'm going to do folder and I'm going to explain why I do photo because I'm doing a local deployment. I can do it locally to the machine and then move the files to where I want them to goal. This also applies when you're going and this is my based on my experience. So in my experience, I have done folder deployments where I choose the folder directly on the server it was going to because of a typo I put in the wrong path and I tried it and tried it and try it and nothing was updating. It turns out I was doing it to the wrong path. I didn't notice until I chosen option that said delete everything in the photo. And then I ended up removing some other could tick off just to get my little website. So my cautious nature, no, that's I've learned through experience, prompts me to always do our deployment to my machine and then the files and move them to the target machine. And that's how I do it. So that's why it's, I'm going to demonstrate to you, based on the experience, you can choose whether or not you will do it my way or you just school streets are the target machine that when there is no right or wrong way, it's just a matter off. Experienced teaching me wisdom. Alright, so I'm going to choose a local folder deployments. So it's going to go into the bin folder released.net five published. Alright, we can click finish and then we can edit. So there's certain things that we want to do. So we can add this point changes the target location if you wish. But then when we go to Settings, we can choose other little configurations. I want the file publish options. So this is the optional stocking on boats. Delete all existing 5p. So what did those is white before learning the new files. And if you don't choose that, what it will do is probably just override what's there or what's in common anyway. So this can be risky because if it's the wrong folder, like I said, it will remove critical files. We can choose the databases. Databases, use this connection string at runtime. And I'm going to take this and I'm going to change his connections to him because I don't want it to use loca, DBMS, SQL local DB. I wanted to use my local host or localhost slash SQL Express, whatever the server name is. You put that there. I will retain the same database name and any other option. And then the steamboat, the migrations. So I'm going to say apply this migration. And what this will do is generate a script based on the current situation of the database and the migrations and everything, right? So we can just go ahead and do that. Click Save and then click Publish. So here you have the target location and this is where it's going to go on my machine, Publish. And once that publishes completed, they'll show you, if you will. Soil or not, which it was in my case, and degeneration of the script was completed successfully. So moving on from just being the initial deployment, this scourge generation step is very important because when you're going to be deploying our like an update, it's already in production on your updating something Amy database changes, new migrations, etc. You will want to provide that script to the database administrators are the senior developer. I mean, if you're a senior developer, then fine. Well, you want this script in order to more, have more control over the database changes. You don't want anybody to just say, oh, I'm migrating data number of spins or do I migration on the deeds obese? Because in development we have fewer concerns about the actual data and integrity than in production. So you want to be careful of that. And let's move forward. So I can control click and go directly to the file system where this was published. And I can take those files and once I'm going to do is in S, So let me just bring up elsewhere at the default website, we know this. We're going to right-click. And then I'm just going to go to explore. So this is now bringing it to the Ionic folder where I'm WW root folder where all web apps must leave. No. Let's just say that this is a server that has multiple applications running. So all of them are running from the server name slash the web app. Mmm. So what we're going to do is create the API has a web up, so we'll get the server name or the machine name slash the APIs and points. Alright, so I'm going to create a folder. I'm just going to call it a total underscore API. And then inside this folder I'm going to place all the files. So if you're a copy and across a network, I would recommend that you archive them so it's easier to copy across. But since it's just for unfolds the fold on the same machine here. It was uneasy operation. Then I want to run the SQL scripts. So I'm just going to go into E f, sorry, I'd kinda quickly EFS gills scripts, open that script file. And then here you'll see that everything that was in the migrations is right here in nice understandable SQL. Alright, so even the migrations that we did, database created all of those things, seeding beta. So the default data that we're putting in all of those migration Anzac here in SQL scripts. So that's why I'm saying that when we are going to be changing the database each time this script is generated, we can actually extract the new stuff and have more control over what we're doing to the data viz. Alright, so here and well, either way the script kind of protects it because they say if the, so that's why I have the migration history table because it takes the snapshots off each migrations. So it says, if this migration doesn't exist, then Karel this oxygen. So it kind of, we'll see if it's done already. I don't need to do it again. Alright. So we can just execute this and let me just go back to the top. So with SQL, if you're, if you're not so familiar with SQL, in order to make sure that the Earth's script is able to run against the database. You can either at the top say Use, and you put in the database names. In this case it'll be OTA listing or you just make sure that the database is selected from the top here in the list of available databases, right? So that's how you can ensure that your ability to read it's on his or her current needs obese when I click execute, the script runs successfully. So know I have the tables if I just refresh, they're all, they're all the ones for the users and hotels and countries, all the ones we created manually, they're all there. So I know that the database is primed and ready. What I'm going to do is continue with sitting of the API web app itself. So Buck in IIS, I'm just going to refresh this list because what it will do is list every folder that is in www root automatically see that. And then what I'm going to do is right-click it and convert tool and application. Before I do that, I'm sorry, I'm sorry. Before we convert this to an application and let's go to the application pool. So an application pool is like a container within which web application or web applications can run over. A single responsibility principle would suggest that you do a pool per AP spread. Because if appall goes on with multiple OPS than all those ups stop working. So you know, for isolation, you can have multiple pools. Someone's in the image API. Pool to nothing too fancy or complicated. The dominant CLR version on when to say no managed code because we're using.NET Core. So this is very, very important. And then we can click okay, so that's fine. Now the relevance of that is that when I'm going back to the previous step and all when I right click and say convert, the application is going to ask me which application pool I want to select. So I can go here and select from this dropdown list hotel API, a pool. That's the one that's I wish for this app to Iranian. And then I can go ahead and click OK. And then you'll notice that it no longer looks like a folder. No, it looks like a little web globe with the well, no, it looks like on up. Alright. So let's take this wire spin. I'm going to just Bros to port 80. And we land on this bid that is seeing 404 address, not phone, alright, but what we would've expected is more or less as swagger documentation. So let me see if maybe when I've prompted it will and there we go. So no, at least we know that we're looking at it from a localhost. And notice this is not local host colon the ports localhost colon the ports, the port number. Let me just show you just so wherever clear, localhost colon, the port number represents the dev environment. In Maya situation, local host by itself. It represents IIS. If you have multiple web, web servers, maybe you have, wow ME, Poisson or Apache, or other web servers running, then you may need to change the ports because right now I have apache. What's it runs on localhost port 8080. Alright, what it is the default on iOS is my default. So local host is what you see when the web app name and then the first page. So at least we know that we're serving of activity from the IIS. Alright, so let us use postman and do a fresh request. So I'm just going to request all the hotels from the API. No notice the link. I hope it's not too small right now I have to see localhost slash hotel, underscore API slash api slash hotel. Alright, so its local slash the web up name slash, the path that we would have settled in our controller. So it has to jump back over. And I'm just doing this soil complete understanding of all these little variables and hold if they apart, right? So the rule that we said was APIs slash controller, I didn't say we could change it. That would probably will know that we're deploying, right? What a point is that because it's API Slashdot means whatever is preceding, it will always go that way. So if it is that we didn't use our web up on call it total up. It could have been localhost slash api special. If it was the mean, if it was a root location off the application server. So in this case it is not, I'm not willing to go into any renaming Just because because your institution might be different from mine and I'm just explaining all the dynamics behind why my ending this van yours may not because he went on a different path. So if you deploy directly, and once again, I have no problem in showing if you deployed your, your API directly to the root of this ionic pulled right of www root, sorry, you didn't make us all pulled away and put it right here at the root, then local host slash swagger would actually serve you. Hope this very pij that we were just looking at in coming from local host, Right? But because of this web up, we have to go into the web app to get to the actual stuff. Alright, so lets us test this request. And when I click send, I am getting a 500 error. And all the cool thing about all of what we did was that we sent all blogging, right? So I can always just go over to my logs folder and take a look at why I'm getting these errors. Alright? So this log file is showing me that something went wrong in the data client login failure for the user. And then it's showing me the name of the user. So in the previous video, I did see permissions will play a very important part in what you're doing, right? So. For our up pool that we just created. In order for the user underneath the up pool to be able to interact with the database, we need to make sure that we give it permission to the database. So what I'm going to do is go over to SQL Server or go back to the database. And then we're going to do two things. Are going to create a login for that up pooled user. And then we're going to add that login to the security for the database. So firstly, new login or well, let me, let me just see if I can do it directly as a user. So under the database it's our goal to users security then users than new user, and then choose windows user. All right, and then to put in that username as pool, that's its domain. And the, basically the name of the pool is the username. Or we can click OK. And if we look in the list, then we will see that that up pool users no, added, no. Let me try this request again. Still getting up 500. Let me treat this a bit. So what I will need to do is give it more permissions. Alright? So we added it to the database books. We didn't give it any membership, so I'm just going to sit it. Does DB Owner? No, you will want to probably be a bit more granular than I am being right know, when setting permissions because the user that may access the database might not, you might not want to give them ownership because ownership music and drop the visa, visa, Andrew Oldham, potentially malicious things as much as it's assisting user. You want to be very security conscious when giving permissions, right? So you may just want to give them data, read, data at or which music and read and write to the database. But they can't do any other critical operation that might compromise the data. Alright? In my situation is my machine there, my users. I'm going to set db owner. So I'm going to say membership DB Owner and own schemas. Db Owner. And generally you notice that the default schema, the deal that you don't have to worry about that that's more database level stuff who just want to get our application up and running. So we can click OK and then we can try again. And then we see here that we're getting data. So we're getting data from our API database. Now just to let you know that some of the security features or I'm a Nazi features, a configurations that's, I might've just Putin might not necessarily work just like that for you there other factors are you that streets are doing these things. The having of permission to give users permissions and all of those things do play a role in whether or not you can successfully complete all the activities like you just saw me do it. Ultimately, however, these are the very basic steps towards getting your application up and running on the configurations needed on the database. And now going back to is there are few things that we want to make sure we get in place. If you remember, when we were setting up our JWT, we added a secret key that we added as an environment variable. No. If you added it to the upsetting style, then you don't have to go through this step. If however you did what I did and added it as a system variable, then we need our API to store that key, right, so that it can handle that operation bites of wherever it is on auto machine. So we're going to go over to the configuration editor. And from the drop-down list to the left, we want to make sure that we have system dot web server and then we're going to choose ASP net core. Alright, so go ahead, conic section, we are going to System.out. Webserver is B.NET Core. And then from the drop-down to the right, we're going down to application hosts, not conflict. Know, when we do those two changes, we can see Environment Variables cone equals 0. So we're just going to click that. And then we're going to add our environment variable. No, the same thing that you had added as the environment key. So I just wanted to unretrieved mine and my name was the word key and my value was this good. Now, however complicated, whoever simply was, The point is that we want it in a secure location and that is what this mechanism is affording us. Alright? So you can just go ahead and put in your name and the key that you selected. And then we can go ahead and close this. Now that it's added. The comment is no one. We can click apply to apply the changes and then restart or pools. So I remember, I did mention that when multiple apps are in the pool, if you if anything happens to the pooled and all of those up schooled on. So I just wanted to restart or pool. We can just do recycle. And then what we'll want to do is test our login and Tolkien retrieve Island and secured access. So let me just double-check that this still, alright, so our API is still works. That's good. Let me attempt to login, so I'm just going to go back to one of my older older requests. Right. And well, actually, I can't use this older request yet because if I attempted so I'm just going to duplicate this. And I went to remove the port number. And I'm also not using HTTPS. Https. That's a whole other level of configuration where I don't want to get too much into that in this, in this lesson, we just want to get our deployment of band running. So local host slash hotel, underscore API, then slash api slash Lothian outgoing slash login. Right. So and I send getting a four oh, one, right? I'm not authorized because this user does not exist. So because we didn't see the user. So if you, if you see that the user, you're probably don't have that problem. So I'm just going to close some of these older requests are at. So let's try to register the same user or at same user. So just change the path. And when we send the request, we see that we get the tool to accepted. So this user's created. Let's go to the database and verve. And we can see that user here, trauma to example.com on the password. Alright, so now that we have the user created, let us try our login operation again to try and get the Tolkien. So the seam requests that we just try and let me send, and here is our Tolkien. Alright? So if we just go to jail with TDA and take a look at our Tolkien, where seeing things that we're used to seeing, right? It's going to say invalid signature because once again, it doesn't know the key was signed with, which is what we've just said, Open the environment variable. But we see that the Tolkien does have the inflammation that we expect. So that's now I'm going to try one off the delete operation soul. Let me try it with the hotel so we know that we have three hotels that we see that, right? I'm going to delete hotel with ID3 from the database so we know that we need our Tolkien and we'll have the link. Let me just change this to hotel. So we're deleting hotel. So I just want to verify that our Tolkien works. And when we do that, we are getting back a tool for. So that means if I go to the database and look in the hotels table, that started off with three, we're only seeing tool. So you see our Tolkien worked our, all our endpoints, at least what we've tested, so firework and so far we have successfully deployed our API at or local. Local IS deployment with our local database of ports. So following these guidelines, you could successfully deployed API within your company sitting or for your personal use, or whatever that situation might be. 50. Create Microsoft Azure Account: Hey guys, in this video we'll be creating our Microsoft a 0 cones. Like I said earlier, we can get started for free. To get to this websites, we go to absorb dot Microsoft.com and then I guess the roads you according to your region or your language. But this is what the website looks are should look like. And you can read through it to see exactly what 0's all abodes. It's about being futuristic, allowing more collaboration, and operating more seamlessly in a closed space, right? They're all over the world and you usually would just choose the region that is closest to you. So I'm actually in the Caribbean region. So my Joel says, region is east to us or East US two. But not for this video. This video we are just creating the columns were not setting up anything about reasons just yet. And so to get started, we can those well, if you have a live account already, then you can just go ahead and sign in with that live up cones. But you can just click Start free. And here they tell you that you can create a free have gone today and you can get started with 12 months of free services. So that's a good deal to me. And if you scroll down, you see 12 months of free, popular, free services plus $200 credit which will expire in 30 days. So they give you $200 a can create V virtual machines, again, create resources in the cloud and experiment until that money is o. And that's really just for one month. But then there are certain services that you just get for free for the rest of the year, and then you will have a few other services that are always free. All right, so what we're going to do is just go ahead and click Start free. Then they'll ask us to sign in with our live of cones. If you have a live account once again, he can go ahead and use that. If you don't have another cone, then you can go ahead and create one. And this is a very recent option to sign in with GitHub. So I have a live a cone that I use, but I'm just going to walk you through the create 1 first. Know the live icon doesn't necessarily have to be at live or at all.com. It doesn't have to be traditional Hotmail account, it can be a Gmail account. So I can actually use the same email address I used for GitHub or by email addresses I use when I'm signing up for things I can use that whether it's Yahoo, Gmail, Hotmail, whatever it is. And just click next. And here it's already, it's telling me that I already have a Microsoft dot gone. So that does this driving my point though, that once you have an e-mail address, it doesn't have to be Hotmail or a traditional alive AECOM boats there, thus creating a Microsoft or Collins for you with that email address. So you can go ahead and sign up. It's a pretty straightforward process. Now they are Conda decided already existed. That's an account I was using to sign up for the free colon. So. I actually just went ahead and logged in and because I really didn't settle much more, I think that your registration process is actually going to look very similar to this regardless, so on to get over the hurdle of putting in your email address and proceeding, then you're probably going to end up on a screen like this where you're going to be asked for your demographic information just for their record keeping my country and are huge on his Jamaica. And I'm quoting him my phone number that I think makes. And then they say, do you want to verify your identity by phone or the want by card? So I'm going to choose takes me by phone and I just got the text. It didn't take long at all. So I'm just going to put in that code and then verify. Now here's the part that might deter you if you're not prepared for it, they will want to verify your identity by card so you won't be charged unless you upgrade, meaning they have different YOU clause subscription plan, so right. No, you're signing up for the free subscription plan. Once that free subscripts on plan is done, then you won't be able to do much on the platform until you send off our new subscripts on brand, which coincides that upgrades. So like I said earlier, there is p As you go And then there's pay-as-you-go dev slash test, which is the one I am on, which is like half the price off the regular PICU cool. So I actually provided my card inflammation when I signed up. And having done that, you can click makes them click agreement if you don't talk about card or you're not comfortable with providing our card details then. Yummy, and you can stop here, that's fine. Later on when we're actually deploying to Azure, you can still see what it will look like and see how beneficial it is to you. What, if you wish, then you can go ahead and provide your information and then click on the agreement and accept the agreement terms and then you would be in the platform. So I'm just going to sign into my Rayleigh cones, might quote unquote Rayleigh cone, but one that I use and show you what a 0 looks like. Well, actually I just typed in Puerto dot 0.com hoping that they would ask me to login, but I did that and it just rewrote that mus into seem a cone that I was just setting up George Williams at gmail.com. So this dashboard, so this is the dashboard at the very basic level, they have a panel to the side here listing ODE. Quite a few services that you can get. But then, because we didn't complete the set of four because I didn't complete the settled, at least then when I go to subscriptions, I'm going to see that I have no subscription, right? So like I will see you in the subscription is how the rate you as a customer, whether your PSU, goal, enterprise or whatever. So if I later on decided that I wanted to provide my information, I can just come back and click add. And then that will bring me to complete the sign of procedure where I actually add the subscription. And so this is a free trial on that war sitting up. Just know you have PSU goal developer support as you have quite a few of them, Alright? So I would probably go with pay as you go. But that yeah, this is all in the in the steps of signing up for Azure, and that is if you wish to proceed with that. But then for this tutorial really and truly, I just wanted you to get as far as the dashboard so that you can see that this is what a Xero looks like. This is what the workload management portal you can set up your virtual machines. But for this course, we'll be looking at up services. 51. Deploy Application and Database to Microsoft Azure: Because we'll come back. So we already set up or a zerocoins and all we want to actually deploy. So before I do that though, I wanted to make sled configuration change to where our log files will be going because in a Xero there's an LC drive, there's no local dry. So what I'm going to do is let Cyril Log creates a folder within the whole folder structure for the project. And that's where the logs will be. So that way when we go to Azure, we don't have to worry about any path or get too fancy. So let's go over and publish. Now that being said, I'm just doing this locally for simplicity, there are tons of more. What'd I say robust boasts logging mechanisms that we can take advantage of understanding this because I wanted to find the most cost-effective way because the other ones costs money as you add on. Alright, so let's just right-click. Go to publish. We're going to set up a new publisher. Fluorophores already have a profile for local deployment, which is a full profile, right? So I can actually just rename this one so I know exactly what it is for. I S profile. Safe. All right. Well then I want a new one. And this one is going to be the Azara profile. So what I want to do is deployed to an Azure up service. No, if you if you don't know that much, I'll quote Azara unclothed. What happens is that you can deploy an application on an obligation as a service kind of constraint, meaning you don't have to worry about this server or anything. They'll just prep night, got nice container for you and put your code there. And then they will hold stuff done that so you get like a cis, right? Or rather that would be the services platform as a service. So they are providing the platform as a service for you to just put her up on it and it will just run. So that's what they mean by the observe is, and then what they wanted to buy a Windows or Linux, we'll use Windows. Otherwise he can do it container or to a container registry or to a virtual machine. So basically the same kind of considerations that would've made with the IIS deployment to either your machine or network machine, you would have to do those kinds of considerations against a VM in Azure because it's the same thing as just a virtual machine CM server. And he Hall, we will choose the platform as a service. The service and then click Next. And then this one, no, it may prompt you to get connected. So you have to say in, in well time-honored descend inside this little Swami, it shows you the subscription resource group. And I don't have many of those. So I'm just going to go ahead and press this plus scientist start building on it on up Service the US for the name. I'm not going to change the name. And then I have a few resource groups, SIR, from foss projects. But I'm going to create a brand new one. I'm going to call it a total listing. Api. So that's the name of that resource group. And then the hosting plan here, I can leave it on the default, but then they do have a free hosting plan. And based on where I am in the world, East US two is my best bet. And choose free. So you might be somewhere else in the world you choose the reason that's closest to you, but based on where I am, East US two is my reasonable choice. Now choose the free deployments. Click OK, then creates. And then after that process is done, we can go ahead and click next and then we can refresh. No apologists is management, so I don't want any management. I'll just skip this step and then we click. So the next screen is showing us what our site URL is going to be. So whatever the AP name is that we sit there dot, dot 0, websites.net because it's free. They give us a sub-domain. And we can always go ahead and buyer on domain if we want, but we won't get that far ahead, but will cause we do have service dependency on a database. They're seeing whether you need to configure your database for connectivity purposes, right? So I need to go and say configure. And then the last those, do you want an on-premises SQL Server database or will it be Azara SQL? So once again, we'll go with the PAS option where they are just giving us a service in the cloud. And we just need to connect. So we have to go ahead and create a brand new instance of a Nitobi service hosting name, hotel service, DVs, AC kind of fill load some things. I'm going to put it in the same resource group as a whole to listing API. There we go. And then database server, I have to create a new one. So it will kind of fill out some things, but I'm going to have to put in my administrative details. So and the password Bartov, which is fairly terribly strict. So just make sure you have a special carton, capital letter and a number and you should be fine once you exceed seven characters. So once you put in all of those details, you can go ahead and click OK. It will auto-fill what it needs to fill within. It doesn't need to one, create the database server and then you would have access to connect to it. Right? And that is completed. So let us go click Next. And then what it will do is say, okay, this is the database connection string name. What is the username? So we have to put back the username that we just use to create the database stuff and the password. And then it will keep it in the Uzziah upsetting section. We can choose the key vault, but I'll just leave that as the default settings there. And then if we want to again actually view the connection string value. So I can actually show you guys that the data source, this is the connection to the actual database in Azure, right? So if I just copy that just for my own purposes. This shows the initial catalogue, that's the database name the user ID will be true for at that dot whatever domain and the password, I used a simple password, of course, in a real-life setting, you'd use a more secure password. So that we can do is go ahead and click Next. And we don't have to touch anything here and just say finish. All right, and now we can click publish. And this might take a while because it has to create a few resources. And this is saying you are publishing the application without bundling the runtime, taking the runtime compatibility. So we can give that. The end result of that check, however, is it's launching the browser and sending me this 500 error. Alright, so at least we know that it is responding. So the API is there, but we still have a few things that we need to do. So let's start off by going to our portal. So only just click manage in a 0 portal, we get navigated to the speed showing us the application running in a 0. All right, so we know it's definitely not adored, it's there. We click bros. It's good to show us the URL, sorry, predicted by HTTPS. And we're getting by that 500. So we're not, we're not any better off than we were before, but at least we can confirm a few things. Now if we go down to configuration, it will kind of show us some of the things like our connection string. All right, so remember that connection string and that hidden value, at least from this connection string, I can see the server for the database. So I'm just going to copy that. Remember I showed you earlier, so I'm just going to copy that. And then in the management studio, I'm going to try and connect to, it's just going to click that. If he already had it open, that's fine. If not, then you're launched in Management Studio and then you put in the server name and whatever credentials are there and click connect. And it will just prompt you to sign in. So what happens is that the firewall is seeing I'm not allowing access to the database from any other source that's outside of 0's. So right now what I want to do is just sign in and then it will add an exception for the IP address that I am using. So that's an important security feature. So I will be behind this IP address. Somebody from their own home with a different IP address won't be able to get to the database unless they sign in and verified just like I'm doing now. So I'll just go ahead and click ok. Of course, there are ways to allow access from everywhere, but we don't need to do that right now. And then when I look in the list of databases, we see our database. So I'm just confirming that our database is. But look at this, there are no tables. And what I'm going to do is edit the profile and go to settings. And we actually skipped this step. I guess we're too eager, right? So we did not do the migration steps, apply this migration on publish. And well, we already used their own connection string with the new hosted database at runtime. So that's Not really necessary to tick again, but that's fine. And I'll save and then I'll just click publish again. And if we just look at the log, you see adding database. And then you see here it gives us some indication of some scripting happening. So let's double-check. And what happens this time around is that because we said apply the migrations, it's actually went ahead and the filled all the tables for us. All right, so that's the really important parts of it. So we didn't have to manually distributable. Once again, it would be prudent of you in our real production live scenario to control this process a bit more than we can do on our personal projects and in our personal time. Alright, so you can check on my other course on deploying and controlling production in the environments. But for this, we're just, we just want to get our API up and running and understand, oh, all the systems worked together. So this is our database currently functioning on your server. So let's go back to our debug console instead of kudos, go to site www root. And then remember that we said Put the love the same root as the file system. So that's why we have access to our logs folder right here, which will show us our log since we've been doing this deployments. So if I just go ahead and download it, we'll open it up in a new browser session. And I just wanted to see why it through the most recent error. So it says something went wrong with an argument not like sip son, some stringer reference error, and some encoding that is supposed to be happening in service extensions line 46. So if we just go and look at the code and see what exactly is happening on that line. It is where we are configuring our JWT. And you see that we're doing all of this. And this is where it says the encoding failed. And it failed because we're looking for C0. And C0 is really an environment variable called key. So remember that we just had to sit that's open. I guess we have to do the same thing as your, alright, so what I'm going to do is go back to our management dashboard, go down to configuration. And then from here I can say new application settings. I'm going to say new application setting is key along with the value. So I mean, I can continuities that same value. I'm going to probably just use a simpler value, but then for consistency between the environment you probably wanted to seem things. So it's, you know, one or the other either use a simple one in dev bodies of complicated one in production or you use one per environments. For security and separation of roles, situations, developer might not be able to just go into production and manipulate anything because he probably doesn't know. But for simplicity, I'm just going to keep the Cmd key across. And I'll click OK. Go ahead and save that, continue. And it will use say we'll restart the application, that's fine. Go ahead and restart. And once that is restarted, I'm going to go to overview, go to burrows are at so that we can't bros anywhere. We're getting this, Sally's, we're now getting a 500. This is the same error that we got if you went through the iOS deployment. That's all we've got, win-wins and route. So if I say slash swagger, then it will lead me to the swagger doc being hosted on our Azure websites. Then I'm just going to go ahead and do a quick test. So I'm going to try to get the country's execute. And then I have successfully retrieved all of the countries currently in the data base. So that means if I tried to use postman, I'm just going to copy this URL over to Postman. And I'm just going to create a new workspace because sometimes you can overcrowd ones. So I'm just going to create a new workspace, cluttered Azur. And then what I'm going to do over here is just Dwell Magazine related requests, right? So country I wanted to get there's no authors is on top. But then as you can see, you can get all the countries right off the but through. Let's try one of those registration attempts and then to do something that is secured. So I'm just going to be flipping between the original workspace where I had the requests already and this new one. So I'll just go over to the post. I just copy this. And instead of boring you with creating it's I just did it. So the new end point would be whatever the website name is slash and then APIs. So that's why I didn't remove it since the IS deployment I lifted because it makes more sense here. Right? Stash a cone slash login and then we can send. And I've got an Arabic cause I had the login payload instead of the register payloads apologists. So we're doing our register and we have the carts payload with the email password. And this is the same one that we tested with from one we're on our local. So I just want to verify that everything still works as it works locally and we get our tool to accepted. So that's good. We're under a truck. So what I can do is repeat the login request. So just click that, bring about the login request and then we can send taller Tolkien. Excellent. And then what we'll do is attempt to delete our creation are something that we know we had said that one of those authorized flag. And of course, I'm not boring you with forming the link where you know they have to form the link properly. The endpoint is api slash hotel with the ID. It's the delete method. And then we add our authorization bearer token and the token that we just got back from the login. And then when we click, we retrieve our tool for no content response. So if I go to the database just to verify, once again, our Azur database, we can verify that we no longer have hotel with the ID3. So we know that we can register a user to our know publicly the diploid API. So if I made this link anymore, you know, any easier to remember, then you could actually browse to it. Granted, by the time you're doing this, listen, this probably no longer exists, but the point is that this is how you can publish your API to the world. And using swagger, you made it easy for anybody to be able to come by and say, Oh, that is how this endpoint works. And these are all of those. And you see that we retained our country V2 for talking amble versioning our APIs. We retain the weather forecast default API, but of course, no, we can clean up all of those things. And some clean ups that I would suggest would be like with country and hotel really and truly, I should have called it the endpoints. Countries and hotels sort of controllers really should've been countries controller and hotels controller. But that's semantics. That's just a matter of presentation on at this point, we can confirm that functionality is up and running.