Blazor WebAssembly Development Guide | Trevoir Williams | Skillshare
Search

Playback Speed


1.0x


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

Blazor WebAssembly Development Guide

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

      1:52

    • 2.

      Install Visual Studio 2019 Community Edition and .Net 5 SDK

      6:46

    • 3.

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

      3:20

    • 4.

      Create a GitHub Account

      2:28

    • 5.

      Create Blazor Project

      7:04

    • 6.

      Tour Project Files and Folders

      19:43

    • 7.

      UPDATE: Create/Upgrade Project to .NET 6

      5:53

    • 8.

      Customize Blazor Layout

      13:11

    • 9.

      Creating Blazor Components

      9:01

    • 10.

      Review and Add Changes to GitHub

      2:25

    • 11.

      Section Overview - Database Operations

      1:31

    • 12.

      Understanding Authentication Provisions

      25:46

    • 13.

      Create Database With Entity Framework Core

      21:18

    • 14.

      Configure Data Seeding

      19:00

    • 15.

      Seed Default User and User-Role - Compare Notes

      6:07

    • 16.

      Review and Add Changes to GitHub

      3:10

    • 17.

      Section Overview - REST API and Database Access Setup

      1:43

    • 18.

      Create and Test REST API Endpoints

      18:10

    • 19.

      Implement Unit of Work

      30:21

    • 20.

      Refactor Existing Controllers to use Unit of Work.

      23:33

    • 21.

      Refactor Existing Controllers to use Unit of Work - Compare Notes

      3:49

    • 22.

      Review and Add Changes to GitHub

      2:56

    • 23.

      Section Overview - Working with Blazor and Data

      3:37

    • 24.

      Blazor Display Data - List

      26:20

    • 25.

      Blazor Display Data - List - Compare Notes

      16:31

    • 26.

      Setup Create Form - Part 1

      22:34

    • 27.

      Setup Create Form - Part 2

      19:26

    • 28.

      Setup Update Form - Part 1

      18:14

    • 29.

      Setup Update Form - Part 2

      9:06

    • 30.

      IMPORTANT - Fix User Audit Fields

      6:33

    • 31.

      IMPORTANT - Fix Vehicle Edit Issue

      5:30

    • 32.

      Add Validation to Forms

      18:16

    • 33.

      Blazor Display Data - Details

      7:40

    • 34.

      Code Clean Up and Add Changes to GitHub

      3:11

    • 35.

      Using a Code-Behind Approach to Blazor Components

      6:22

    • 36.

      Global Error Handling

      21:36

    • 37.

      Add Changes to GitHub

      1:43

    • 38.

      Customize Identity Layout and Logic

      20:55

    • 39.

      JavaScript Interop With Third Party Libraries

      19:24

    • 40.

      File Upload Support

      26:06

    • 41.

      Generic HttpClient Repository

      15:06

    • 42.

      UPDATE: Removing Magic Strings

      11:52

    • 43.

      IMPORTANT - Fix Delete Endpoint

      1:33

    • 44.

      Progressive Web Application Support

      4:26

    • 45.

      Add Changes to GitHub

      8:58

    • 46.

      Deploy to Azure

      27:13

  • --
  • 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.

159

Students

--

Project

About This Class

Learn to build a modern Blazor application while implementing enterprise level concepts, design patterns, and features.

Overview

Writing modern web applications with a rich UI can be tedious. Blazor gives us .NET developers the chance to leverage our C# skills and build interactive web UIs. In this course, Modern Web Development with Blazor and .NET 5, you will gain the ability to build web applications using Blazor. We will explore: setting up your first Blazor application; how to work with an API and how data binding works; how to create components and integrate JavaScript components.

When you are finished this course, you will have the skills and knowledge to build a web application using Blazor.

Why Develop With Blazor?

The most popular JavaScript client-side web frameworks have been Angular, React, Vue and others. In this course, we keep it .NET by using Blazor, which is Microsoft's response to that monopoly.

Blazor allows you to create a Single Page Application, on top of .NET Core and continue coding in C# (without needing to flip between C# and JavaScript too much). Blazor apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries.

Blazor WebAssembly

Blazor can run your client-side C# code directly in the browser, using WebAssembly (WASM for short). Because it's real .NET running on WebAssembly, you can re-use code and libraries from server-side parts of your application.

We will be exploring many intricacies of the Blazor life-cycle, data flow, JavaScript Interoperability and general development activities and nuances.

Deploy To Microsoft Azure Cloud

Azure Web App Service is key to deploying the API and Blazor Server Applications. We will also enlist the use of Azure SQL for Database to support our API.

Build A Strong Foundation in .NET 5 Programming With Blazor:

  • Build a Single Page Application client side UI using Blazor and .NET 5

  • Design a Database Using Entity Framework Core

  • Repository Pattern and Dependency Injection

  • Progressive Web Application (PWA) with Blazor

  • Understand the REST API and Client UI design principles

  • Understand C# and .Net Core Web Syntax

  • Understand how to customize Blazor app layouts

  • Understand User Authentication and Authorization in Blazor

  • Understand Identity Core and Identity Server

  • Handle Blazor Application User Authentication State

  • Consume REST Web API in Blazor Application

  • Manage Packages with NuGet Manager

  • 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 10 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.

The course is complete with working files hosted on GitHub, with the inclusion of some files to make it easier for you to replicate the code being demonstrated. You will be able to work alongside the author as you work through each lecture and will receive a verifiable certificate of completion upon finishing the course.

Meet Your Teacher

Teacher Profile Image

Trevoir Williams

Jamaican Software Engineer

Teacher

Related Skills

Development Web Development
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: Welcome to this course, modern web development with blazer and done it five. In this course, you'll learn how to build a blazer application from the grown up using enterprise level techniques and features. I'm your instructor, terroir Williams and I have over 10 years of experience both implementing systems as well as training people just like you to develop them. So I can assure you this is the course for you and you're going to be in good hands. Now by way of introduction, we want to know what is blazer Blaser is one of Microsoft's newest web development technologies. Yes, we had the silver light and the light switch, but not blazer, looks like it's here to stay. It gives us creates alternative to JavaScript when we consider building interactive single-page applications, it's lightweight, it's versatile, and supports both WebAssembly as well as our regular dotnet application deployment scenarios. In this course, you're going to learn basic development through building up fully functional WebAssembly, please our application. You're also going to understand the whole dotnet five workflow and folder structure. And ultimately we want to, of course, use our skills to go into the workplace with them, so on clean code and we're going to be exploring some of our options when it comes to these things. This course, you're going to learn about Entity Framework Core. You're newer to learn how to manipulate and develop our rest API where, what's on the stun dotnet Core Services, who I went to look at coding patterns, source control, deployment and hosting. This course is jam packed with information to guide you to success. Now this is a big course that's quiet some bits of content and, you know, I'm not going to go through all of it. It's going to come out as we go along. And I'm really excited to have you here. See you in the next lesson. 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. No workloads really refer to the libraries or the 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 and 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 select 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 don't load 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 to 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 create a live account, which point you would want to just use your Microsoft issued at live at all loci are taught me a lot calm at 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. However, once you are on this landing screen, this is where you proceed to create a project. So I'm not going to create our projects. No, I'm just showing you what to expect. So you just go to Create New Project. And then under that you'd be able to choose your template. So as this is a blazer course, we would want to look for blazer. You go ahead and search for templates if you don't see it as one of the first things here. Once you do that, you can give it the name. Once again, we're not actually creating anything yet. When you hit Next, then you choose the framework that you prefer. So then you will start seeing dotnet Core 3.1, dotnet five, and dotnet Sikhs, which has long-term support. So at this point, since we're using Visual Studio 2022, you'd probably want to maximize your potential and use dotnet six. But then you do see that you do have other options. But when we come back and we're actually creating a project and we'll walk through what exactly needs to be selected so far, no, once you've gotten this far, then you have successfully installed Visual Studio 20226. 4. Create a 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. Create Blazor Project: Hey guys, welcome back. So in this video we're going to spend much time. We just want to go ahead and create a brand new blazer project. So we're going to do is open up our Visual Studio and then we'll go to create a new project. And then from here, we will want to look for the blazer up templates. So you may not have it to the left if you've never created on before, but then you wouldn't be able to find it in the list of templates here. And then based on the workloads that you may have installed when setting up Visual Studio. It may not be seen at the top. So you can always just use a search and you can type in blazer and it will filter that list of project template, bringing the blazer up to the top. So you can go ahead and double click that. And then for the project name based on the type of project which we will be building, which is a current application or current management application. I'll just go ahead and call it current management so you can name it whatever you're more comfortable with. But after you give it the name, you just go ahead and click Create. And then the next screen is a very critical screen. So let me walk you through the options that are presented and what are the implications of either one. So firstly, we have the option of the blazer server up. And if you read the description is a template for creating, but he has a server up that run server side and it runs using.NET Core as well. Signal are so pretty much this is just going to give us a website just like any other.NET Core website, if you've ever used.net core before, and it has to be deployed on a server, maybe ISR on just that code, deploy our regular website that how this one would have to be deployed. It uses signal or whoever to kind of give us a real time feel to our application. So it's not the worst option, but of course, context will define if you need to use this one, r naught. The blazer Web Assembly option, however, gives us the option to have a Web Assembly app. And web, web assembly is an open standard that allows applications to run directly inside the browser. This means that we will be creating a verb powerful web application that will interact with an API, but it does not need a server to be hosted. Alright, so once a client or somebody browses to this website, the initial low time may take longer than the server set up, but it will actually download the entire application and all of the dependencies right there onto the person's computer. And it will run entirely out of the browser, reducing the need for the round-trip to the server every time it needs data. The implications of this null would be that all of your binaries, all of your dependencies are and know when to be on somebody else's machine. And if they have any intentions towards you are towards whatever it is your application can do, then they could do some harm if they know what they're looking for. So you know, you have to take each one in stride and made the best decision based on the context. So for this actual course, we'll be using Web Assembly. But then if you look to the right, you'll see that you have the option of making. Dominant core hosted Web Assembly up. So this is like a hybrid between a server and our subassembly up. So I'm actually going to do that one because it gives us the ability to create the whole up the Web Assembly side, which is the user interface, as well as the API side, which would represent the server as opposed to the server app, which we already discussed is really just like any other dominate core application. If you're not familiar with 0.1x core applications with an MVC IRAs are websites, applications work. Then you can check out my other courses where we go through those kinds of websites. But for now, we will be building the web Assembly up using the ASP.net core hosted and the progressive web applications. Or the purpose of the Progressive Web Application option is to allow us to create an app that people can actually don't load onto their machine. So we're moving from DOE loading to the browser and nowhere talking about downloading to your machine. So the website would actually come down to your machine and you can run it and execute it just like you would any other program on your machine. So that is what a progressive web application would allow. Alright, so you would have to spool up a browser every time you wanted to just though ticket and usage. And another benefit is that progressive web applications can also be downloaded onto mobile phones and run almost natively. So it's a very powerful feature to into. So we'll go ahead and include both ASP.net core hosted and progressive web applications. But then I just wanted to buck chuck a bit before we move on. And we want to look at our authentication options so we can read No, it's on no authentication. We can change that and we can see individual user a cone. So what this will do is actually allow us to have the ability to manage all of our authentication, authorization and user related operation. Everything would come built-in, wouldn't have to do much more work to include all of those libraries. And this distro of Web Assembly and dominate core hosted application. It actually allows us to use identity server, which is built on the open off standards, which is basically like, right? No, that is the top tier security standard for authentication. Most websites across the internet uses, and it's allows us to have support for local authentication as well as third party authentication. So that was quite a bit of information coming at you when we're creating this album. Does Latino all of the options. What the pros and cons of each option are. Once again, reinforcing that context will determine which one is best for your situation. Right now we want to do the work, the blazer Web Assembly up with the.NET Core hosted progressive web application features included, we want to add individually User Accounts as authentication. And of course it's dot net five core course. So we need to make sure that we have done it five selected. All right, so then we can go ahead and click Create. And once that is completed, where greeted with Visual Studio and our solution explorer and this whole interface. And we see quite a few files in our solution explorer. So I'm going to pause right there because you've got lots of information. Just know you can review that section about your different options on what they all mean. But in the next video, I'm going to give you a tour of the folder structure so we can understand exactly what each file is for and how they all come together to make our application. 6. Tour Project Files and Folders: Hey guys, welcome back. So in this lesson, we just wanted to take a quick tour of blazer, all the files that are included in this project templates. So you can remember that when we created this project, we want selected blazer Web Assembly two emitted.net Korea hosted. We included the progressive web application feature sets, as well as included authentication. So quite a few things happened right there. And on top of all of this, it is a.net five or.NET Core five projects. So we just wanted to have a full appreciation on, I'll pull everything in this project works. So let us start off with a fund that will my solution explorer just to my left, if this is the first course they're doing with me, just hold my Visual Studio Setup. Otherwise, you would know that you can drag it to the left, you can drag it to the right and any side, but it feels more natural for me. So I will always go to the left when I'm showing the folder structure where you can just follow along with your settle. So let us start off with the fact that when we look in the solution explorer, we have our solution, of course, whatever you named Project or the solution. But then you notice that you have three projects. You have car or into management, client, current management server, and current management dot shared. So you've got three projects. Altough the box, because we've created our web assembly core hosted application. So for context, if we didn't choose that.NET Core hosted option, then we would've only gotten the car rental management client project. So it wouldn't have gotten these tool, would have just gotten this Web Assembly project. And then we would have to connect to an API somewhere and do what we have to do in order for it to actually have functionality. Once again, this is almost like a static website, this entire project, all these files I'm highlighting when it compiles it, that program, that project, that website, so many ways of putting it. We'll just don't load to the client mushy and into the browser and run from there. However, because we made it dominate core hosted, what Visual Studio afforded of snow is the ability to actually create the APA all in one. So the dots server application will serve as the API. So this will have to go on some server, maybe an IIS server in hosts are on Uzziah or wherever. And then we'll just connect across the internet from the Web Assembly to our API project or API functionalities that we have in our server project. All right, so in a nutshell, that's why we have these two projects, dot server and client. The DOD shared pretty much is like, you know, bridging I get between the two because there might be classes that the tool might have in common or data objects. So instead of creating them twice, they just give us a dot shared. So both projects scanner reference the doc shared section and leverage the already created crosses our resources. Now you'd probably realize that each time I click Up Project, the actual project file here, that CSB file, it opens up a tab and it's just an XML file. So this Is, all I want to point out is the fact that they are all saying target framework.net 5, right? So they're all targeting.net five. So lets us take a look at the client project for a bit. So on the client under this node you have your dependencies. And if you want to drill down, you see analyzers or the project say C8 or France is the shared project right there, or the packages. I'm not going to delve too much into what packages and frameworks and analyzers do as the project goes on. Those who make more under properties, we have this file called Launch settings.js sandwich. Got it just has some configurations for our application to be able to run. When it's running. It should run on the address issues http localhost than if it's SSL or HTTPS, it will have that port number. And there are the configurations there which on a case-by-case basis, we might need to come here and change things, but I don't want to sit here and talk you through every little one because chances are you may not ever need to interact with some of these. So let's move on. So www root, that is going to store our static files or CSS resources. It comes built-in with Bootstrap and open iconic. So they're giving you quite a few things out of the box to help you start your design. You have the index.html file. If you've been doing what bys n for awhile, you know that index should always be your first files. So what happens is that when the client application runs, it will always look to the index file. And then index file is where we define references for all of these things. We have our title. So you are, if you're familiar with HTML and the basic skeleton, this should not look too foreign to you up until at least the part where it says div ID up loading. And then it gives an error if we can't load. So this is like our little template file to say this div where the app will be rendered. Alright, the manifest JSON as well as the service worker. And these two really are there to support or progressive web application ambitions. Alright, so when we get to that point, then we can look more into these, but that's his why you have these two files. If you don't want to have these two files, then it's prone to cause it didn't choose progressive web applications. We'll move on to pages and pages. That is where we will be defining literarily the pages that we need to build out our application. So you can see it came with some already given to us, one for authentication, alright, one as a sample counter, fetch data and the index, alright, so indexes where it will go first. And as we build load application, we'll be adding more pages. And with more pages come more roads shared will have any pages are components. So these are pages. You'll notice that they're the same file extension dot razor, what the page would be the entire thing. Whereas r component is reusable in multiple places. So that's why on the shared we would call these components because any of the nav menu, which you know, would show up on many different pages all over. You have the main layout. Which is, this is our actual templates where it just renders the body off what is in the page itself. Alright, survey prompts. All of these are just reusable components and they are shared because there can be shared across the different pages. We have the imports file, which talks about the different libraries that we would want to be using inside of our pHs and our components. We'll build on that as we go along with the app.js file, which kind of lines certain sections. So here you see it has cascading authentication on state. And then it talks about if it's not authorized, what it should do and if it's not found, what did she do say can actually kind of extend the original routing mechanism of the blazer up to say that under certain circumstances by default you should do this or do that. So that's what appraiser app.all razor kinda facility. Then we move on to our program.cs file. Now here is a very, very, very important file. In this file, we actually see it up that we want all of these things to be in place by the time the app starts. Alright, so program.cs is going to contain our boot-strapping mechanism, the startup configuration. So basically anything you see here is seeing at startup, at the time of startup, this is what I wanted to happen. So let's take for instance, this, this builder, the builders saying I want to build up a bunch of configurations for execution. Alright, so if you look at the first line, this is where it defines a builder. And then the last line executes that builder. So everything in between is adding to the builder. Builder dot root components, add up hashtag up. Where did we see hashtag up or what relevance is that? If we look back at the index file in our www rule to see that we have a div with the ID up. Alright, so that's really just seeing that we want to add up. Up is just that global keyword for the blazer up tool, whatever component or whatever HTML element has the ID. If you know CSS, you didn't know that the hashtag really means ID. So any element that has the ID up, alright, and as it goes along, it builds, it creates a default client, which is going to look at the server project that Kim built-in with our template. We also have this swan where we're seeing, I'd scope down, we're adding the, Well, the very client to the HTTP client builder. So all of this is being done for you. If you had another API that you wanted to add or interrupt too, if then you'd have to do something similar to make sure that this APA is readily accessible from anywhere else in your blazer application. And then as we go along, we see that we add some facility for authorization. Alright, so that's basically in a nutshell, really in a nutshell for the client up and all of the files involved. As we go along, we'll be making changes and certain things will become clearer and certain things will make more sense. Now let's look at the server application and I'm just going to gloss over things that the two have in common anyway. So dependencies that looks the same way. Once again, it has a dependency on the client project, and it has a dependency on the shared project. Alright. We move on to properties. And the properties we have the lawn settings file, we've seen that before. We also have this one for a service dependencies, which we'll talk about having a dependency on MS. Sql. You may need to extend that. You may need to change that. We can leave that alone for now. Then we go on to areas. So areas is just was auto-generated because we said we wanted to include the identity services are the individual accounts authentication features. So we've got this area's section that's allows us to kind of interact with login and logout and so on. You don't see the files and instead know what should we need to customize them. We can actually generate them and what we want. But for now, that's what we have the areas for us it onto remove that. We have the controllers folder. And if you've ever worked with MVC, you'd understand what our controller is. If not, then a controller is really just file or a class file that has commands. See, I have accepted our request and I will give you our response. Our request could be I want to go to this page. When you click on a link, you're sending a request to a controller. The controller receives your request and then gives you the answer in the form of the webpage that you requested. If that web page is not available, that's a GET 400 fours and if something goes wrong in between, then you get an error. So that's pretty much what our controller is four, so we'll be using API controllers because like I said, the server project really serves a purpose. Servicing the client project with an API. So we have an example. I will have two controllers. I'm not going to get too much into this one with the OID c configuration controller because this, this is a configuration controller. And later on when we're doing authentication stuff, will get to understand this a bit more. What Farnell weather forecast controller just talks about the different endpoints and it's a nice little sample to let you see how things go together and how they might work. So when you request the weather forecast, this endpoint gets hits, are this action gets hit, so controller's actions and then the action gets hit, and then it returns this data. And that data is sent through the API buckles at a client, and that's what the user will see. So that is it in a nutshell, data will define some of our database configurations and classes and so on. So right, no, we don't need to get too much into that later on when we're sitting in top, we'll get into those files. Models are basically just abstractions of the data classes. And then we can move on to pages and hear it in the server project Girona, C1, ph. And really and truly, I'm not sure if we'll ever really see and interact with the speech or any other page that we do here. Because once again, the focal point of our AP is the client side, the client application, client project, right? So the pH is folder's there, but we won't be doing much there. Anyway. We have up settings.js son once again another configuration file. We have the program.cs. And if you look at the program.cs here, it's slightly different from the program.cs in the client. But they're really doing the same thing because the program.cs in the client, it's the same class program except it is doing all of this in the main function, right? If you know C sharp once a, the first thing it's going to look for as a program.cs file, and it's going to execute the main function. That's how they operate. So in the server project, we have the startup, it's sorry, we have the program.cs. It has the main function also, but at a main function is calling another function. And this other function it's calling pretty much is executing what is in the startup.js. So if you look in the style.css, then you'll see a very similar configuration and setup to what we saw in the program.cs in the client side. So it's really a very similar thing. This is just setting up bootstrapper as to say that when the application starts, these are services and features that I want to make sure I have been pleased. So red here it seemed that I wanted to connect to the database that can be found at default connection. We haven't set that up yet, but it's there. It's seeing we want to add some exception filtering. We want to add identity using the application user model. We'll get more into that later on. And we want to add identity server said it's a would be getting identity server capabilities, which is when the handler authentication and authorization, we wants to use some JWT authentication. So all of that can come out of the box without us having to do too much configuration. And then it wants to add controllers with views and add facility for ease of pages. You'll also see that there's the middleware section where it's adding other features. So I could go line by line. But then some of them, when you look at them, they're kind of self-explanatory and as we go along will interact with them once more. So that's really it for the server and client projects. And then when we look at the weather forecast, will see here that this is really just the model, right? So if we look at the references, you see that this model, this file is being referenced in both the client application. So if that reference you see that it uses it in the client or in the fetch data component. And it also uses it in the server. Side in the API call. So I'm just pointing that totes to highlight what the shared project is far because this one model can service both projects and so on. We have things in common between the two. We can just define them inside the shared. So I'm just going to run this application so they can see what it looks like. Alright, so this is our base template for our blazer up. Once again, this is our client projects running. So if you look at the port number four for three it for, let me just quickly show you the parallel. So if I go to client and then go to Properties lawn sittings, there it is for 4384. So that is the client application we have running here. So the counter, when we click, look at that, we can click and it changes. And I suddenly interrupted when we do fetch data, look at what it did just know. So it said fetching data, checking login state, and then it's launching this login page. This login page is really coming from the Identity Services. You see down here it seeing car into management dots server. So remember that we had that area's section that I pointed out is really for the authentication stuff, right? So that pages really rendering from here. So that's how identity server works, were you can actually sit stuck to just rewrote, reroute, sorry, an authenticated request to the identity server, and then that Pj will be served up. And once it's satisfied, then it will move on. If I can, the app.js and here is where it did that. So it said when it's not authorized, right, then redirect to login. So reader and a redirect to login, that's a component. If we look at what that component is doing, and that component is in shared redirect to login it seeing, navigate to authentication on slash login with our return URL and all sorts of things. So I'm just showing you how everything is tightly coupled, just know everything looked so seamless. The only thing that's not really seen this about this is that it's not, it doesn't look like the general theme for the pH that we started off with, right? That's the only thing that doesn't look very seamless. But the point is that if I didn't explain all of that to you, and I realize I have so many moving parts working towards rendering all of this. So right, and all our login and register stuff won't work because there are things we need to do. But I'm just showing you how the blades are outlooks. And hopefully you enjoyed this store where we went through how all of these things kind of work together. And if there's still things are unclear, boat, then as we go along they will make more sense. So stay tuned. Next up we'll talk about the look and feel of the whole template and how we can modify it. And as we go along, we'll just go on adding functionality and exploring more and more boats are options in this blazer application. 7. UPDATE: Create/Upgrade Project to .NET 6: Hey guys, In this lesson we're going to look at two things. One, how to create the blazer WebAssembly project using dotnet 6. And we'll also look at how you can update it if you've already created it in donot five, which is surprisingly very easy. So let's get started with how we create it. So all I have to do opening Visual Studio 2022 instead of 2019 because six is unique to 2022. So I can just go ahead and create a new project. I will select my blazer WebAssembly app, template it next, and then I'll give it my name. So that is car and management net 6. I'm saying net 6 because I already have the dotnet five project with the name current management in the same directory. If this is the first one that you're creating with that name, you do not need to put on the net six or you can give it whatever name you feel comfortable with. So after selecting the name, we go to next, and then we will want to select which framework so we can use dotnet five, we can use Dani core 3.1, but dotnet six is unique to Visual Studio 2020. To also to get the most out of this course, you would want to use Don at five because this course is taught within the context of done at five. And everything that is taught here is forward compatible with dotnet 6, among other things. So you will want to use dotnet six and you will want to choose authentication type to be individual cones. And you can take each of the following options. Once you get through all of that, you can go ahead and hit Create. Now let's say you already have the dotnet five project created and we already went through a tour of the folders. And what each file in at a higher level really stands for, really means and how it's used in the project. So if we want to update it to dotnet six, all we really have to do, and just a few steps. One, we want to change the target framework. So you want to click that CSV file. Does that file at the top of the project? Just click it once and it will open up this editable file. Target framework is 6. So that would've been seeing 5. You can change that to six. And you also want to add these two packages so you can just hit Pause and retype them as necessary. So you want to add those two packages and then you want to, if you do a build, you're going to get some errors. Don't panic because all you really need to do is do the same thing for the server project. Lets you target met six and add the same two. So you could actually just copy them from the client and paste inside of the server file. After you've done that, you want to probably update the shared folder also to dotnet six. That part is really optional. You can do that also. Then you want to. So there are, there are a few steps, but they're really simple steps. So I'm just giving you little by little. So for me the easiest thing to do to update the packages, because what happens though is that we're targeting dotnet six, but everything by default would be targeting dotnet five. So you want to get everything up to the same version so you can just record the solution at this point and go to Manage NuGet packages for solution, which will then allow you to just run updates across all of your projects in one go. So I'll just jump over to updates, which in a few seconds will be populated. There we go. And all of these things need to be updated from their current five-point whatever versions to six. Sorry, just go ahead and say update. Of course, we have to accept and a license agreements if you're not very familiar with this step as in what NuGet package manager is and how it helps though, or later on, all of that will make sense to you. So with all of those updates done, I'm still getting some errors and I think that's because they're filtering our weird little by little. But I think some projects have not yet caught on. So I'm going to do build, do a rebuild solution. And now we have everything successfully rebuilt and 0 arrows. So that's basically how it works. And as you go along using Visual Studio 2022, you'll see that the tooling is much better. You'll be seeing things that you won't necessarily be seeing on my screen because I'll be teaching most of the course using 2019. But you'll be getting certain code hinting you see here that they can, they're asking if you want to allow IntelliJ code to monitor you and help it. In other words, In teleco does an enhanced intellisense which gives you better code hinting than the standard stops. So you are going to have absolute fun. Another cool feature that they've introduced, his hot reload, you can see here with this fireball. So when we're building author interfaces, you're going to see like I'm going to make certain CSS changes or certain things, then I'll have to restart. That's one of the limitations of 2019. If not, if you're using 2022, you can actually just do a hot reload and then it can just refresh the interface without you having to restart the build. If all of that is punished to you, don't worry as you go along, you will get used to it and you start to appreciate all of those little things. And if you are already familiar with the Visual Studio interface, you're going to see some amazing things coming out of this new IDE. If you cannot upgrade, then that's no problem. Everything that is in this course is friendly towards either one of the environments. So that's it for now. I'll see you in the next lesson. 8. Customize Blazor Layout: Hey guys, welcome back. In this lesson, we will be studying our blazer up. Know if you're familiar with any form of what development you'd know that styling a web application really just has to do with modify and the CSS and the HTML to make sure that we can deliver the best user experience to anybody who is going to be interacting with our up. If you are by extension familiar with.net MVC applications or.NET Core MVC application server result pages. You'd know that we get this layout file layout.css HTML, which basically sets the tone for how all the pages would look. Blazer does it a bit differently books at the end of the day, it is the same concept of HTML and CSS as we saw on the tour. We have a bunch of HTML files. We have some CSS files, and what we're going to be doing, some minor tweaks will be transforming what is on the screen null to look something more like this. So I'm giving it tended to dark field, right? I'm taking off the purple highlighter to cough the bar at the top, and I move the navigation section to the left. So while we're doing this activity, it's not that much, but it will give us a sense of where we can go to modify Watts. And we'll also get a little feel of whole CSS. Css isolation works in blazer. Now just the buck chuck a bit. So one of the more important files will be modified in general when we are going to be adding me because some themes, custom scripts or anything like that to the entire blazer up would be the index.html file because this sets the tone for the index for the sorry HTML document with a head tags, all the CSS links, all the js dot niece, her own upfront, right, so you would end up modifying this at some point, however, beyond that, everything gets loaded into our div with the ID up. So beyond or index.html Node. The next most important file would be our main Leo trays are which then renders a div called page, gives us our nav menu to the side, right? And then it gives us our main content area where we have the login display up top that a boat link, and then what comes in the body. So here is where a lot of the magic happens in terms of the CSS and this is where CSS isolation comes in. There isn't one big css file. I mean, yes, we do have CSS files available to us in the CSS folder. We have app.js, CSS, which has some general CSS for the app which really corresponds to the up here or the index file because there's a reference, right? But then when it comes to the main layout, it has its own CSS file like we saw before. So from here I can control certain elements that are only in this component. And I can apply those CSS styles, whatever it is accordingly. So that is the pole of the CSS isolation. I can have a CSS file dedicated to Ariza components separate from the general UP CSS. Let's start off by a change in the color of the navbar. So to get to the navbar CSS, I can say OK, the navbar would be enough. Menu is found in this div called sidebar. If I go over to the main Leodes dot, dot CSS, I see the class sidebar. So what did those who don't know is learned during gradient, which is why you see kind of changing shaded in purple if you want to run again and look at it. But that's why it changes shade in purple. So what I'm going to do is just comment this out. I mean, you can delete it if you want someone to retain it. And I'm going to put in another style as his background color and then hashtag and that value sake and just tear that off. And that's what gives it that nice agree not to dark kind of background, right? So let's just see what that looks like. Alright, so I made the change and I loaded up the app and I'm not seeing the changes. And now this is just something with the caching. You have a number of things you can do here. You can clear your history and try again and whatever browser you're using. Or you can hold on on control and press F5. So Ryan, No, that is the gradient but grown for the navbar when I control F5, then I get my dark background. There we go. All right, so if you run into any difficulty with that, does control F5 and you should be fine. So that's what happens when I change the CSS in that specific CSS file for that component. So let's see what else we can do. I didn't say we wanted to remove this top bar. So let me go back over to the chord, back to the main menu. And this top row here it is, top Reuters in the login display, as well as an abode link. I don't want any of that, so I'm just going to kind of move the login display a bit and take that. As a matter of fact, in the demo I had the login display being displayed nav menu. So what I can do is take login display, right? So that's just a reference to the whole component called login display. Then I'll go to the nav menu and I'm still in debug mode, but refresh sooner, soon, soon enough, sorry. And what I'm going to do over in the nav menu is paste our login display component, right? So enough menu has buttons for what do we have here? We have home, where have the counter and we have the fetch. Those are the three many items that we see, home counter Fitch. And then it has something to collapse the menu and that's fine. So what we need to do know is actually makes sure that login display falls in line with how everything else loops. Because as we saw it, there were really just links in the navbar. So I'm going to refresh and there we can see what this looks like. Alright, and this is what I'm seeing. So I'm seeing the two links. The top bar is gone. So accomplished that what the toolings are just, they're, they're not quite fitting in with the design of our navbar. So let us modify what is in the login display to kind of look like this. And I'm just going to copy this because I know that the way the links need to look in the navbar is dependent on this entire block. We need that l i, and we need all of those classes along the way. So I'm just going to copy this, jump over to the login display. And then over here we will see that we have the authorized under non unauthorized views. However, we also noticed that they're really just a bunch of anchor tags, right? So you'll notice that that blazer actually comes with certain components that help you to emulate some HTML elements, right? So nav link would be one such component which gives you an anchor tag or it's just an blazer way of seeing Oncotype cause you notice they both have the same H ref, right? So I can just stay this H ref, replace it here. And I'm just going to transform this LI. Well, I mean the LI is going to give me the type of link I need to fit into the navbar. So I'm really transforming this anchor tag into this LI. So that's it fits in, right? So the text that's I want be split would be what would be displayed here in this anchor tag, the hello usernames and us replace home. And for this would be the Profiles. So I think for the icon, I'm going to use OID persons. So we all have, we have these icons available to us through open iconic. It's already included in the project. So that's how we get that little house on the plus sign and so on, on the nav bar. Just in case you're not familiar with. If you are, then you should be feeling right at all. Alright? So that is the one for if the person is authorized, meaning the person has already logged in that one says profile, the next one says logos. So I'm going to just duplicate that I bit of code and replace what I need to replace now and look at the difference with this. This one is a button. This one was done on cryptology. This one is a button. Let's see what the button does. The button has onclick event that says Being begin psi naught. And then down below you see a code block with that very click event begin psi naught. And then what it does is it navigates to this URL. So I could, you know, I could keep the button, but then I'm using nav links. So instead of modeling the top, I'll just keep it consistent of unraveling here, of innovating here. So what I'll do is set the HRF for the logo nav link to be the same URL it would have navigated to. So the age ref here is authentications slash logos. Alright? And then this one, I think there is a logos Open icon. If I'm not mistaken, there we go. I dash dash logo, right? And then I'm going to just comment out these two because I don't need them. I've just replaced them. The anchor tag for the person's profile as well as the logo button. I've replaced them with tool nav links going to the same places, right? So you can pause here and you can attempt to do the same with these two. I'll just do it. So I just replaced the login and register with the corresponding LI tags. Alright, and for the register I have o, i dash Burson for the icon, and then for the login or dashed login, dash login, sorry. Alright. And then really and truly this block of code becomes useless because there's nothing that's going to be calling it anyway. But later on we'll get into writing the code and understanding these code blocks and events. However, let's take a quick look at what this looks like. Alright, so this is what we get. No, you'll see that it kind of looks a bit more at home with all the other links look both at the same time. It doesn't, they still don't quite fit in. And this is another point of the blazer, the CSS isolation part of blazer where yes, they're in the component for the nav bar. But this is another component all by itself. This is the login display component, and we're just calling it from login, from the nav menu component. But they're two different components. So the CSS that applies for the nav menu will not apply here because this is an entirely different components. So then what I would have to do to get these links to display how every other link displays. And I'll just take this entire author as you from the login display copy and then come over here. And instead of referencing the login display component, I am just going to do piece all of that content there. Alright, so then we have the authorize, you authorize unaware of the allies, that should be displayed accordingly. And everything falls into the nav menu components, which means all of the styling for the component will now be applied. So that's us restart and see what that. And then when we come back we see something looking different. Right? So that looks a bit better to me. Like, oh, it looks snow. You can do is go ahead and click along the way and you see that the novel link works there. And if I go back and then I click Register and see that it works there also. And so we can rest assured that all of our links work. Everything looks uniform. And once again, it, apart from the nuances with us having to share our CS, or they're not sure the CSS across components. You can see where it's rather the same thing when it comes to styling in blazers, just that they give you the ability to apply some unique CSS component if you want. But then ultimately you can style everything from one protease as with any other application. 9. Creating Blazor Components: In this lesson, we are going to be taking a look at some blazer components and how we can create them, what they can be used for. And this is just a gloss over wherever and started the AR application that we're still learning about, our blazer environment and all of the things that it affords us. So I'm not going to get too in depth, but what I want to talk about is whole one, we can create more pages. And two, how we can create components that can be embedded on pages. So when we talk about a page, we really mean something that we can navigate to write. So when I click counter, it changes, it goes to the counter page and you can see it in the URL ii goes from the local host address slash counter. If I click comb, it goes back, right? These to fetch data is going to attempt to go to fetch data, but then it is being protected from unauthorized access. And so it will navigate to the login page. We're not getting into that just yet. But what I want to do is create another page, like all we have the counter peach and then create our component that we can then embed on that page so we can see a top-end before our eyes. Before we get into that though, let's take a look at what the counter page has. So the counter page, which is really just a component, is found in pages and you'll see it cone Teradata razor. And the reasons that it's really just a component. If you look at shared, you see that all of them are there with the arrays are. And we just went through what Login display dose versus Nev Many versus all of these, right? So cold winter and these share one thing. They're all rays are components. However, shared implies that these components are used across many applications. Versus the Pij is where the, the component serves as literally a page. So when you look at this component for counter, you'll see that it has this directive of top at page. And then it says the root server will only clicked on or alter its on Colin's SRE. It said local host address slash counter. Well that's why. Alright, either way I have all of the content. We remember that we had the word colon terror. We add that current cones, and then we had our button. And what happens is that when you click the button there's an onclick event that says, well, increment by one. Once again, we'll get into all onclick and so on, little later on. So I'm not going to spend too much time on that. So if I wanted to create another page, I could go to Pages right-click say razor component. And then from here I can give this component a name. So let us say I want to call this one some people. Ph, alright, because that's all it really is going to be at this point. So just wanted to sample page. Now the first thing that I wanted to do is let it know that it's upbeat. So I need I'd signed page up top and then I give it its route. So I say slash sample page. This is what you have to type in to get to these components. Alright? And let me just say that's an h3. So let me use an H5 and say this is full page. Alright, now to get to it from the menu, because no hover new piece that I want to navigate to have to go to my nav menu component, which I still have all of these comments, no problem. But then I need to add it to the navbar saw laughter is really just take a copy of that and change it. So this one says it's ref fetch data. It's rough counter. What does that mean? Well, counter has root counter fetch data has the route slash fetch data. So to get to my page, I need slash sample page. So for the new menu item, I'm just going to say h or f is equal to sample page. Of course I have to change the text so that it's clear that that's what it's for. And I'm not going to change anything else. Because once again, this is an experimental. So when I run this application, I'm going to see my new menu items sample page. And when I click that, we navigate to sample page with our content right? And notice the route slash sample page. So if I said some page one, then it's basically going to say for four days nothing at this address. It doesn't know what that is. Some verbiage, however, will always get me back to my page. So let's create our components that were, you know, components that can be reusable. So if it's something that we want to use multiple times multiple please is embedded here, but display fully there, which we're going to look into. Once again, this is just a preview of the capabilities. But let us look at actually putting this portion into a component and then embedding this component on our pitch. So let's say I wanted components, but that didn't quite want to put them in the same folder shared, right? So it's as easy as creating a new folder. File organization is always very important, so I'm just going to call it components, right? So we know components. There we go. And then here I can say add razor component. And then I'm going to call this some people pij component, our sample page content components. And just being very explicit so that I can remember what it was for, right? So now we have this component. I can put anything I want in there. I can put let's say I did didn't want this to just be printed there. I wanted to put it inside this components may be put in a button. Alright? And this one is just going to say Hello, world, right? Of course they're using Bootstrap, foresaw all the Bootstrap four classes applies. I can say btn dark, just to give it some character. And then now I have this component, right? No, I want the contents of this component to be embedded in this page. Alright, so what I can do here is simply call on this component as though it was a tug. Alright? But then you notice now it has a red squiggly line and it doesn't quite have that green. Let's see if I can find another one, right? So when we're dealing with components, you always want to see that green embolden the text. You don't quite see that here. Why? Because we need to include a library to be able to access this one because this is not in the same directory as the sample page. It's in another directory and it doesn't know or view doesn't nobody structure. So we can add a using statement up here where we see using current management, that's our project name, current management dot plants are, which is our project name.com, which is our folder named as the namespace. And once we have that using statement, we can then access the component and you see everything looks right. Of course, using statements can get messy. So what you can do alternatively is put them in the imports. So in the imports you can stack them up using say Zelda using all those libraries that you know, you're going to be using our cross multiple views. You can just go ahead and include them in that imports file. Every view is going to be looking at that or every components are, is the candidate inputs. So it will know, knows that this is where it should look. So let's just run that and see what that looks like. Alright, so we're back in our up and I look at sample page and here it is. So I'm seeing some garbage content and component, right? So this is sample page that's h3 tag that Kim originally with r component. There it is. But then our sample page content component has its own title, has the content and Hazara button that we know to be dark leather or so forth theme, right, so that's just once again, a quick introduction or quick gloss over how we can create our own components. And as we build on this application, we're going to see more and more of the capabilities coming out. 10. Review and Add Changes to GitHub: Hey guys, welcome back. So we're here at the end of our first module where what we did was to create a new blazer application. We had a quick walkthrough of all the files, hold the each play a part in this whole ecosystem. And then we looked at how we can customize the look and feel of it and even create a few components for ourselves. So we haven't done much, but at least now we have a TS stuff lot blazer is and if it seemed intimidating before middle, you probably realize it's really just another.NET Core application at this point. Or I want to just keep track of where it changes. And we'll be taking shorter cones like this at the end of every module will just check in or quotes are GitHub repositories so that we have our basic checkpoints in the history of the evolution of our project. I hope you already created your GitHub account. And what we need to do to move forward would just be to add to source control. So if you look in the bottom right hand corner of your Visual Studio webs, sorry, window. You should see Add to source control. So you can go ahead and click that and you should see get. And then this window comes up. And if it prompts you to login, then you provide your GitHub credentials. It's already knows who I am and it knows the local path. My cones, I'm the owner, the repository name. I can give it a description. I can make it private or public. I'm going to make it public so that you guys can access it, of course. And I would recommend that you make it public generally so that other people can come across and see the work that you're doing. And it can help to build your portfolio for it to share with future employers. So you can go ahead and make it private. However, if you, if you saw desirable to admit my in public once again, and then just say create and push. The results of all of these actions will be the creation of your own GitHub repository. Once again, if you made it public, then on somebody can come on GitHub and search for your handle than they can find the project. But next stop, we're going to start looking at some fun stuff. We're going to start looking at bit more add towed, the authentication engine works, as well as how we can start putting database behind our application. 11. Section Overview - Database Operations: Hey guys, welcome back. In this section of the course, we're going to be looking at some of the data related operations that can be afforded to us through our whole blazer application. So when we had created or application we add indicates that we wanted authentication on provisions. And out of the box, what the bootstrapper did was give us access to the identity server, which we took a brief look at difficult to Arras and identity and pages. You'll see that we have something here that kind of indicates some identity related operations. And identity is the library that Microsoft uses for user management sessions, storage, all those things. So login, logout, and all of those wonderful features come out of the box through the identity core library. By extension, they would've also included the Entity Framework Core libraries that allow us to do my grayish on sets up a database context in a quote first method and actually build out the database from our op and then scuffled it afterwards. So in this section we'll be taking a step-by-step approach to understanding how all of these pieces come together and how exactly we're going to build our database for our blazer up because it doesn't make sense. We start building all the underwriting functionality if we don't have anywhere to storage, right? So when we come back, we'll start looking at those things in bits and bits. 12. Understanding Authentication Provisions: Alright, welcome back guys. In this lesson, we want to kind of understand all of the authentication provisions afforded to us through this whole bootstrapped include authentication, project creation right there quite a few moving parts that if you don't quite understand what you are looking at can look overwhelming, Or you could probably just ignore them and everything works. But it's always good when you are working on a project and you will have a full appreciation of how everything comes together. So I just wanted to walk you through some of the libraries and the functions that were included in the project from the beginning to kind of give you an idea, what is there and what came out of the box. So I'm going to start off in those startup file for our server project. And we kinda went through this before, but I wanted to kind of take my time and point out certain things again. No one we're adding to the service, bootstrapper services dot default identity. So this came out of the box, of course. And what this does, it says I want to add identity library to my application using the model that is indicated here. So by default we have identity user. That is our default model given to us by Microsoft dot ASP.net core identity. So that's a default user that once you have included authentication, you have access to this user. However, that users kind of limited in terms of the fields that it, it allows. Because sometimes, you know, far user to sign up on your website. You want first name, last name, you want other things. So what they did was create a custom class bit based on identity uses. So it's inheriting all the fields from identity user. And then you can extend this glass and you can put in first name, last name, date of birth, or the things that identity user out of the box just did not have. When we scuffle scuffled database, you kind of see how exactly are what exactly gets generated based on just this direct inheritance. And then we'll see how we can extend it afterwards. So we're adding a default and entity in the form of application user and just say, you know, you can have multiple user types. So application uses the default that they gave us. We can create toggles if we wants, I won't go there, right? And although, and then we have the option. So here we can point or what kind of authentication options this user should abide by. Do they need to confirm their cones upon sign-up? Right? So in other words, we need to load up to setup an emailing mechanism, you know, like when you sign up on your website and they email it to confirm your accountant and confirm and then you can say and that is what this opsin basically says. Do you want to enforce that? So I'm going to put this the falls at least Farnell goes or they're not willing to go into any emailing stuff just yet. So I'm going to say false, meaning you can sand in red Nandan, sorry, he can send up or register at null and then he can sign in immediately after. So that's what this option, pretty much those and actually this option section is actually optional. Right, so you don't have to specify options. You can remove that if you want. And you can add other options if you want. The CMMI that falls far null. And then we are saying that we want to add all of this to the application DB contexts, which represents our connection to the database. So would have pointed that told earlier where it's looking for default connection as our connections to the database. Later on though, we'll get all of those configurations in, in on our fingers and understand them better. Next up, we have services that identity server, no, identity server is actually a set of libraries that, you know, it's used to control access for modern applications. And it includes different capabilities like single sign-on identity management, authorization, API, security, all sorts of wonderful things. And it's based on the Open Auth standard. So it's like industry level, OpenID standard. It's like industrial level protection for your application. So even without identity server identity core, that core set of libraries can deliver a lot of the functions, but an identity server kind of extends the capabilities. And it's usually given as a standalone application for strictly management of the identities, right? In this situation, they included these libraries in our whole blazer up and so we can reap all the benefits from it. And later on. Well, in addition to adding the identity server, then goes on to say where adding API authorization for application user and that storage area. Alright, so API authorization would pretty much say that it configures the identity server for API based authorization, which generally means that it's going to use identity server JWT. Alright, so JWT, JSON web tokens, that's probably the highest standards of security that done API can have right now. All of that is coming out of the box. If you have though, my other course on blazer, then you'd see where we build the API ourselves, we put in our JWT ourselves and then we add to meet provisions still, the JWT in the client side. Everything is connected and wired up out of the box for you. When we build our blazer up using this project template configure section, we see that we have up I use identity server, then use authentication and use authorization. So these three middlewares be Skelly, just kinda put the icing on the cake to let our application, or that this is what we intend to have. We want the ability to allow somebody to sign in and register, and also on the ability to restrict. All of these libraries should be relative to what provisions are given to us through the identity server. Know, another part I wanted to point O would be the areas. So we have looked at the areas before. He's not in any great detail, but in this section we have those pages and the pages, they're empty. All we have is that login partial. However, whenever we run our app, we click login or register, we see that the actually goes over to another section. Let's just quickly take up. All right, so when I click register, then it goes over to the server application on an initialism Register page. If I go to login, it's still in the server up showing me a login page. However, we have already established that there are no pages with those names are addresses in our server application because well, we don't have any pages. We only have this controller here that does oil DC configuration. And well, we don't have Pj is named register and login. So what would have to do if you wanted to get those pages and by extension on customize their look and feel because he can see that they don't look like the website. They don't feel like they're part of our web application. What we can do here is right-click areas go to Add and then we will see new scaffolded item. Then we go down to identity, and then we can go ahead and click add. And then it's going to do some work in the background. And then it's going to allow us to decide which sit off files we want to actually scaffold into our projects. So I can say override off, which means he will just materialize all of us and add them to this whole folder structure. I can be very selective and say that I only want the Leodes, I only want maybe the register and login and anything else can be fine. So I'm just going to say override all files, no harm in that right? After the data contexts majority can establishes the application DB context. And then I can say add. And then after we do that, we'll see that we now have a new folder and a few new files, right? And if I look in a cone that I'm going to see all the fast. So you've got to register and login. And then, well, I have the coordinate, I can modify them and made them look like more like they're part of my app bar. And these take old some of the things that make it, it makes them look like they're outside children off the whole optimum trend to build. Alright. We can also modify their Laozi by creating our own Leo pij. Well, it says that the path leo tear in the view start is pages slash shared slash layout.css. And if you look in pages, then slash shared, we don't see a layout.css HTML, so we could create our own little pitch and then override that if necessary. But the point is that all of these things out here and customizable. So if you've ever worked with identity core in MVC IRAs are pages, then this shouldn't be too foreign to you. You should feel right at home. If this is your first time, then this is exactly how you can start customizing your registration, your login page, and anything in any dominate core application. It's not limited to just the razor. Alright. Or well, Blaser Other it's not limited to blazer. And I wanted to move on from the visual stuff and talk more about the database stuff because I did say that that would've been the focal point of this whole discussion. So let's us go down to data. And in data we see that we have two libraries to folders, right? Or a folder and a file header. We have the Migrations folder with two files in there. And then we have the application DB context. So when we click on Application DB contexts, we see here that it is application DB context just stuck class. It's inheriting from API authorization DB context, which is contexts or loading the application users. So these once again are built-in libraries and even those hover over API authorization, you'll see that it's saying it's a database obstruction for combined DB context using identity and identity server. All right, so I've seen identity DB context being used here for the, for the inheriting class. I've seen DB context being used here. But then because we said that we wanted API authorization, right? Remember that we said up here, add API authorization, right? So then we have the API authorization DB context being used to facilitate that. So we're sending overall functionality from this library to our dB contexts, our application DB contexts embodies all the features here and whatever else we're going to put in. Alright. Here we have a constructor where is allowing us to pass in some options. And you realize that a lot of things are very customizable and he comes to this and they give us quite a few options out of the box. So customising, maybe limited to just Watson out of the box and maybe minor tweaks based on our personal requirements. So that's our application DB context file. If we backtrack a bit though and go to migrations, what you see here is the first migration allowing for the creation of the identity schema. So all tough the box, they're giving us what we need to create, all of the identity related tables or when they said Entity related tables of SBI net roles. This is the roles table to store roles and application in all administrator, user, et cetera. We also have a spin at users and SBI net users is going to be generated based on the default fields that I mentioned calm with the identity user, right? So remember we want to go to application user. We say identity user. If I tried to look at the definition of that, then let me see. Expose that. Well, they don't really, really expose the fields that are there and that's no problem. But the identity user is going to automatically embody ID, username, email, email, confirm password, hash, all of these fields. So when I said that we may need to extend these fields by adding to application user. That's what I meant. Maybe we want firstName, lastName and other things as fields in this database table. So later on we'll look at extending them. But Farnell, this, this migration is allowing us to create all of the default tables and then we can extend. You see here we get device schools. This is from identity server, cause if you use identity core, you wouldn't have seen that library. You wouldn't see persisted grants is being ruled cleans. Sbi, net User Claims, user logins, all of those things. We get out of the box with our identity core library. Alright? So what we're going to do now is actually scaffold this database does so far our looking at this code, we have no tangible evidence of anything. If we tried to login, right, normally would fail as almost alpha. Let's try to login because we see that it goes to the login page. Well, let's see what happens when you actually try to do so. Alright, so I'm going to try and register, and let's see what happens. All right, so now it's saying I database operation failed while trying to process this request. And then it said he cannot open this database and all sorts of things that are sending us that we need to apply the migration, that's the same file that we're just looking at, apply the migration and run the commands, and then we can track again. So let us go ahead and setup what we need to set up so that we can start creating these tables in our database. So in the OB settings.js on it did say he couldn't find a database phone that x-y-z. So it was inferring that the database will be found out the address that we outlined in our app settings.js IN file. Alright, so we have the server being local DB, which is the server that I came with Visual Studio. It's very much attached to Visual Studio. We don't have to go into Management Studio for that. However, if you want to use another database server, like maybe you have a developer instance or an SQL Express instance. You just need to change that server name right there, right? So you could make it local host, you could make it dot SQL Express, whatever it is. You can go ahead and change that. And I'll leave it does local DB because, you know, for development purposes, I want it right here in Visual Studio. And I'm going to change the name of the database. So this is a default name, is spin it dash, current management dot server dash, and some good value. I don't need all of that. Someone's going to call it a current on management underscore DB. So I'm going to take off all of that stuff and make it that. Okay. There we go. So after I've cleaned up my app settings.js, JSON file, null Lionel where null, I am seeing that if this database does not already exist, this is the one I want to create. So and it said add the migration or apply the migration rather through running update database. What it was seeing was that when I say update database, it's going to create the database if it doesn't already exist, and then create the supporting tables according to this migration file. If you pay attention to this migration file, you'll notice that it's really just like a C-sharp translation of what's going to happen in SQL, right? Id, table, column, string. The type is going to be invited charge. So if you know databases, then you start seeing that this is really just C-sharp. Telling us what the sequel is going to be heard. It's not too complicated, it's not even that finds C, To be honest, there is just a builder. And then at the end of building up everything that shouldn't happen, it's just going to execute, right? It's just going to create. So lets us look at how we create the database. So I'm going to go to Package Manager console. If you don't have a tear in your Visual Studio, then he can always go to tools and new get package manager and you'll see Package Manager console so you can always just bring it up like that. And then we're going to say update hyphen database. After running that command is going to build a project and then let us know when it is done. No, that was very quick. It started to build, it was successful and then it says done. Nothing visibly. There is no difference, right? I don't see like anything happened on new files got added to the project, but let us look at the database. So I'm going to bring up MySQL Server Object Explorer. If you don't see that, you just go to View and you will see SQL Server Object Explorer. So you can just bring that up and look at local DB databases. And you see that I have quite a few databases, including my current management db, which is the one that we just created. And if I expand that and look in tables, then I'm going to see all of the tables that were outlined in this file that is being displayed to my right. So we have the roles table, we have the users table. All of these tables are there and available for our use. Alright, so there are two parts to when we want to update the database, where you have the migration, which is this kind of file C. And these are the changes at the MBL atomic. Alright, so he keeps track of every time we make a change to the database, it's like keeping track of it. So if you're a database developer and traditionally you built the database, but then when the application is being built to make changes, it's kind of harder to truck that you change this column to that and it's more money. Well, when we do migrations in the chord first sitting, it allows us to see that at this point this was what was in place. The next point, this is what changes were made and it helps us keep track. So let us make a few changes. And the change I'm going to make is just the application user, right? We did say that we wanted to extend it. So I'm just going to say I want to add String firstname. And I'm going to add string lastname. Alright, so those are the two things that I want to add. And then once again, you're not limited to watch. You cannot, you cannot date of birth, it cannot address whatever it is you need on an application user, you agony, but not autonomy and changes to this file. And this file is directly related to my application DB context, right? Then it's going to realize that the version that was, that existed and created a database last time is no different from what I have applied. So no, I need them to know I generate a migration file. I can say add hyphen migration. And then I can see added name to user. Something lead us something indicative of the changes that were made. And then I just go ahead and press enter a law that to build. And then it's going to create a migration files. So now if you look in migrations, you'll see that there's another file even timestamped. So this one is zeroed because that's grown 0 literally, right? This one though isn't about timestamps to say at this point in time on this day, you made that migration with whichever name you gave it. And then if we look at the files, you'll see that it's just going to say add a column firstName. So the table is being at users. That's the type and it's nullable. You see, that's all it's doing. Alright? And then you're going to see that you have or don't function. So this one is because the change is smaller, it looks much easier to actually read and understand what it is doing. And once again, it's really just C-sharp. Danny was what does a boat up in, in, in SQL? And the Don't you see in that, should I reverse the migration are reverse the changes, then this is what it should do, drop column and drop that. So we have the OP saying what we're about to do and they don't seeing what should be unburned, should we change our mind? Alright, notice that we have the Migration. We just run a database. After ever migration, we run an update database and then the database already exists. So it's literally just going to do on obesity. If it didn't exist, the first one, then it did create and update. So if I look back at the database and look at my ASP net users table and look at the columns. Then we are going to see that we have firstname and lastname. So I really didn't show you that there weren't near before, but based on the initial migration, first_name and last_name weren't there. We just went and added them to application user and know they're there. Alright, so that is a nice quick introduction to how we do migrations and how we go about setting up your identity and making sure that we have adequate information on our users when we're about to build our applications. Right now I'm going to actually do our registration again and see, see if we can get through. So the buzzword that's I'm using is password outside one because they're very strict to the parser policy phi, let's say neglect the one that, well, firstly, if I don't meet them much, You see that's it's sending me that much. And if I neglect the one, it's telling me that it's too weak, right? So out of the box you have a strong enough password policy which you can increase the strength of once again through the options. But I think this is complicated enough for me, right? And also its password, password with an AdSense and number one at the end, we click Register and see what happens. So we're getting much further than we got last time. And look at that. Just let that just by running two commands. I didn't even need to add first name and last name to get this thing working because he was working a long time ago. And I'll just save this in my browser. Well, you see here we, it's telling us hello, right? Remember when we customized our login display to kinda move those nav buttons over so they know it saying hello, the person logged in, right? It's allowing me to logout. And then I think if I click this, it will bring up profile, right, authentication and slash profile. Okay, so this is going right back to the server, to identity manager. I sorry, identity server manage and then index writes. There we go. So that's, that's what we're looking at right now. Alright, so when we scuffle the pages nowhere have access to all of these pages are that we can customize, look and field a field off, right? So right now it's showing the profile with the username and the phone number is user name, phone number, again, James, a phone number c. So we can give all of these things out of the box with very few customizations, with very little effort, with very little effort from us, we can get our login and registration system up and running in our blazer application. Once again, go on to kind of modify this. Kinda looks like we're not going in and out of the application. But the reality is that identity server is really like a standalone application. So, you know, it's, it's goes both ways. It depends on what you need are even if you want to give the user access to all of these things, because you might not want to give them access to change their phone number and email address at will and so on. You may want to control all of that to yourself. So that's a nice quick introduction to the whole identity server. And whoa, identity works in a blazer application. I hope that you understand it a bit better and nowhere are going to move on to actually creating our database tables to support the rest of the features of our application. 13. Create Database With Entity Framework Core: Hey guys, welcome back. So in this lesson we're going to start creating the database with the supporting tables for our current management applications right now all we already have our user support tables for the sign-in for trucking cleans, all those wonderful things or to have those. And we already discussed how we got the got them in. No, we want to create our own tables to add to the database later on. So I have on screen here Nieto relationship diagram, an entity relationship diagram. You know, it goes by many names, but this diagram is showing the database tables and who has relationships with through. Alright. So what we can see here is that we already have, we already know some of these tables that already know that we have the device schools persist grounds all these ASP net user related tables we already know off because those were all scaffolded for us through the Identity Services, right? To the right, however, we have additional tables that we are going to be creating this point. So we have colors. And I'm just starting off with those with no foreign keys or no dependencies. So we have colors, we have models, we have mics, right? Because it's a car into management system. When we add a vehicle, we want to make sure that we capture what color it is. One modality is what make it is. And in the vehicle noise related to all of those costs is going to have the make model and the caller ID. Let me zoom in a bit in case it's a bit small, right? So we have the Vin and we have other fields that we want to capture all the car. We're going to have bookings so that we can track who when it was rented by whom. And it did indeed old and then calculate the cost, all those wonderful things, but have the costumers and basic information on the customers and so on so that customers will not be users, which is where we have a customer's table different from a users table. If we if we made it that the customers could login and access the system and do what they wanted to do, then we wouldn't have to create a customer still could just use the ASP net users table extended for a customer type of operation. And then we could just use the to store everything abode of customers. So once again, context is everything. How you design your tables, so you design your application on all of those things are governed by either year objectives are the objectives of the business for which this system is being designed. So what we want to do now is start creating these tables. So we have 1236 tables that we need to create. Let's get to it. No, in terms of your project layout and the overall architecture and so on, that jury, Zoltan, where's the best place to create your tables or create your class files that will then become tables. What I mean is we already have client client projects where you have a server project. However, shared project, which serves the purpose of having class files, are any resources that would be shared between the two based on which pattern you're going to be using. You may want to put your data classes inside a shared folder because then you don't want to have them duplicated. You don't want to have one version of them in the server project, one version of them in a client. You just put them in shared on both projects can access them, which is what we're going to do know. Well, I'm just giving you a context just in case you're knitting your eyebrow may already have another idea that's no problem. In other situations, people make data access layers where they create the domain classes different, right? They'll mean, meaning the classes that then become the tables. They creates another project for them. And then they obstruct the domain chaos is from the client classes, meaning the server and the database related operational. Again, see the data classes within the client is using a different version of them for client purposes. And that's what we'll start looking at that pattern called like MVVM, wary of view models or API as I call them details. So later on we'll get into the patterns. I have nothing against buttons. I love patterns and see where they're good. But right now we just want to do the basics to get it up and running. Because maybe those wanted to build an app that can talk to the database blue from the database and look pretty right. So sometimes you don't need to go to that level of obstruction, but then the abstractions do help with when you need to scale the application. I'm putting more features on more tables and so on. And you have fewer proteases you After Guandu maintenance, that's a purple self patterns. Alright? So retinal, what we're going to do is create a folder in this shared. And I'm going to call this folder, let's just call it domain. Alright? So domain is going to have all of our domain classes. So you can see here with a forecast is already insured. But why is it ensured? Because our controller here, weather forecast is when to use that file. Here we go, weather forecast. And in all our clients said if we looked at fetched data, they knew would see that it's also using weather forecasts. So that's the purpose of putting it in shared so both of these projects can get access to it. So right, no, we're not going to put in that abstraction between the domain classes for the database operations on for the client. I'm just going to use the same class files to kind of show hole at a basic level weekend facilitate talking to the data. So we're going to start off with the simple tables, right? So don't mean new class. And one of the simplest tables was me. All right, so our mic table, and I'm going to make this public so that everybody can access it. Public class mc, we can add, and here are just a prop tub twice and then it generates this lock. So string and writes me would be like Toyota Honda. You know, that's the brand. So they can call it brand if you want. That's fine. We also had what we'll call audit fields. Red, because of course we need an ID field as ever table should have. We also want feels that say date created and updated. Well, the thing with these three fields would be that these three fields actually will repeat across all the tables, right? So every table is going to have to have an ID and we want to have date created and deeds updated. And we could even pushed the envelope to see created by an updated by. So let's do that also. So that we know who did watch stringing created by and updated by. Those would be strings. Because then we want to store the username of the person who carried out the operation on Earth. So string updated by string created by the time created date of D, the title painted red. But then once again, these fields will repeat across all the tables because this is me when I do model and went out these fees again. So what I'm going to do is create like a base model, basically a tomato. So I'm just going to create another class and I wanted to call it base data model, Barbies domain model. Let me call it domain model. It doesn't really matter, but the point is that I wanted to be a base, right? I don't want to make it public, abstract, not abstract. This means that I can't instantiate this class by itself, right? But then this abstract class is going to have in these fields. So I'm going to take ID out of me, put it in this abstract class. I'm also going to take created by date periods at all of these audit fields. And I'm going to put them inside of this abstract domain class. And then what I can do is just inherit. Alright, so public class make colon B Islam in models. So no mic actually will have whatever field there as well as the, so it's the same principle like what we just looked at with our identity user versus application. User application uses inheriting from the base class add entity user, and then we can extend it as we need. So here is the extension for me, right? So then every other one that we're going to do can follow that same principle. So make model. Once again public. It is going to inherit from base domain model. So the button says the audit fields and then I'm going to put name. Now the reason I didn't put name inside the base is that not every tip isn't up names. I don't want to put anything inside the beast that not every table is going to hub, right? So while it may look foolish to have make and model, both having Name and then another one is going to have name in the form of colors, color, color. And we're also going to give it the field name. We're going to make it inherit based domain model. And of course you have to make it public. All right, but then that's it for the 11-cis name. So I'm now going to wearable near him anymore. So let's get into some more complicated tables. And I always see even, even in developing code first, are developing databases always start with the tables that tub and all foreign keys are no dependencies. Because then when you get to the dependence is the dependent data or data that's it depending on rather is already there, right? So if we wanted to do vehicle next, what we do to the domain Gosse. And then vehicle is the name of this one. Same treatment, public inherit from our base domain model. All right? And then what we want in set of vehicle would be year module ID and then up virtual field for the model, right? So this represents our, our foreign key right here. Alright, so what, so this, it's automatically going to say, well, I know that there is a table or a corresponding data class, domain class called model. I know it has an ID field, so model ID's automatically go into map to the ID field in the corresponding class called model. Alright, so Entity Framework is going to do that for you automatically. If, if a normal building databases using SQL server, you know that you have to go in and manually say, this is our relationship with this Entity Framework was generated with infer this relationship for you. And then including this field, which is the type model, and we just call it module. But this node allows it to kind of imply that an inner join might be necessary. So without writing all the code for an inner join, you would automatically just bring about the related data for us. So we're storing the ID, whatever we can access name and who created it on any other detail that we need to. We may get virtual because virtual and music can be overridden if we wanted to. What that's fine. We can You don't necessarily have to make it virtual. I'm winter included though. So then we have public ID, public int, make ID with the same treatments. We have color with color ID, same treatment, same principle. And then we have the Vin, the license plate number, and then we have booking. So here is a perfect example of why we should create the depending the required table first. So the vehicle requires the booking table cause it has a dependency there or there's some far off relationship between them, except this one. You don't notice it doesn't have that ID and object peering. And this should actually check over my work. This should actually be a list of looking representing the rental records. Right. So a vehicle can be on multiple bookings. So let me change that from our entire chord symbol gains. So that's, it's more clear. Alright, so this would be a list of bookings for anyone vehicle. Pretty much that's what it means. Which means that when we create a booking class, and I can just hover over that and say generate booking in a new file, generic class in a new file. C created booking for US public class booking inherit from obese domain model. And then booking is going to have relationship with a vehicle, right? So for anyone booking, you're getting a vehicle, right? So we are going to have the date in it alt, right. So u comma u make a booking. What time? I would just go ahead and include any missing libraries there. We have the customer. So what customer? So we need to create a customer table, once again, dependency. And then we have the rates. All right, well, I think actually, no, that's, I'm looking at my original design. I'm thinking that the rate should probably be on the vehicle because generally speaking, the realities on the vehicle, and then however long you take the vehicle, that's how much money off the piece. So I'm going to put there in salary over here. So I'm putting on new field inside of vehicle called Bilbo or in tolerate. Alright, so when we put the V could in the system, we're going to put that this vehicle is going to be like $2 thousand on oh, sorry. In Jamaica dot dot would be the general grades 2000 laws on all our rights are twofold and Dasa D, since we're dealing with bookings, the inundate old. So per day or per night you have the vehicle. That's a somewhat GOP. And then we can always just calculate based on what's here. So that's it for the booking. But then of course we still need customer so we can do the same thing. We just generate the four customer, right? It's an OAEP or customer. And then we saw that we inherit from the base domain model. And then our fields here would be tucks idea address, email address, and contact number. And then of course, we are going to want to make sure that we have a representation for the relationship. So the thing is that this is like a two-way relationship, that really a two-way relationship where it's just making sure that these two related entities knowable each other. So this is one booking can only belong to one customer, but then a customer can have multiple bookings, right? So yes, the booking as one representation of a customer at a time, but then the customer has multiple bookings, just like we saw with the vehicles. Right. So the same kind of list of bookings that we have in the vehicles you have to put in the customers table and include any missing references. There we go. And then we can just do a build to make sure that everything is OK. So we can do a bill just to make sure everything is okay. Alright, so we have all of our domain files in our shared project with the domain folder, right, so that's the namespace. Know, in order to get our database to generate the table is that correspond with these, right? Well, we need to do is go over to our data in our server project, go to the application DB context. And then we need to list them out here. So to list them out, notice not inside the constructor, this is our constructor. So underneath dot constructor, but in the class, we need to start seeing public VB set the data type and then the name that we'll want the tables the hub. So notice this one is singular, one is pleura, right? The class, generally, the entity is singular, the grass because our class represents one instance off. But then the table is the collection of these instances, right? So the table name would be vehicles, what the class of which the table is based on would-be vehicle. Alright, so again, those go ahead and include the missing library using current dat. No, it knows where it's finding these things from. So we can just go ahead and include that. So follow this pattern, public DB set, angle bracket, the class name, close angled bracket, the class name pluralized, and then get onsets so he can just go ahead and include that for all of them for color, MY model customer booking. Alright? So once you've done all of this, the next step would be to create a migration because null, when we'd create a migration is going to look backup application DB context. And notice that the last migration didn't have any of the snow. This is there. I clearly have changes to make. So let me document these changes, right? So Package Manager, console, add hyphen migration. And then we are going to see added, let's say application tables. And then once we do that is going to build. And then it's going to give us our migration files showing once again, what did sub-bullets hoodoo is about to create a table called colours. And the columns include the ID column, which is int, and it's automatically setting it does identity. So you know that if you did it in the database yourself, you would have to set it as primary keys synthetase identity. This is happening all by itself. It's inferring that the id column is going to be the primary key there it is, said the primary key as the ID column, right? Customers, same treatment. And then for the relationships, you'll see that it's sitting some foreign key constraints here. Says a foreign key for colors, colors, ID, FK, vehicles. So this is a vehicle stable and it seeing in setting up foreign key between the vehicles table and the colors table, where the caller ID reliefs to the ID column from the caller's table. All of that is eaten FRD for you by Entity Framework. Alright? And the same way we have the web that don't wear on new, we can just reverse the changes. So the point is that anytime you're about to make a change or you have made a change to the whether you added a new table or you added new fields or change the fields. Once you've made that change, all they have to do is ADA migration. It will go through and compare what's new with what null obtains. And then it will document the changes in this fashion. And then once you have done that, you can say update database. So sometimes, you know, when you make certain changes it may lead to data loss. Like you could change that data type or you remove a field. It will warn you. So far I haven't done anything that would lead to data loss. But let us take a look at what is an auto-generated. So here is the current management database hallway lifted last time. If I just refresh and then go and take a look at it again, then we're going to see our new tables, bookings, colors, customers, makes models, vehicles, all of those things. And pretty much that if we generated a diagram of this, it would look if not just like then very similar to what I've displayed at the beginning of this lesson. So now we have created our own tables in addition to everything else. So next up we want to look at how we seed data into the database. Seeding means we put some sample data in some of these tables. And then we come back, we'll take a look at that. 14. Configure Data Seeding: Welcome back guys. In this lesson, we'll be looking at ceding data and I'll seeding data has the essential purpose of giving us some sample data to start off with. You know, like we want to make sure that I user is always in the B2B is when the application begins or we wanted to make sure that there are a few basic bid self-information in tables. Whenever the application begins. When I talk bubble, when the application begins, I mean like if we have to install this different site, we finish the application on our machine, but I would have to deploy it on a different server. When we first run the application and load it up, the seating would fill the database with the basic data. So they just wanted to take a look at how this works. So calm and things that get seated. Maybe default rules. So maybe it, I've lived the administrator role versus the user role on all the thing that might get seeded would be maybe default makes on models in our situation and colors. Things that you probably don't necessarily want people to have to manage themselves, or at least he wanted to give some basic data once again. So to seed some data into our database, what would have to do is create an override for our default function on model creating. So once we have the application DB context and it's inheriting from any form of DB context. It's going to have a function that is protected and we can override it. And to be called void and see into the senses are telling me what function it is I'm trying to build, so on model creating and it will do all of that for you, no problem. So whatever it generates, you can leave that alone. But then underneath that null, we can start seeing what we want. So I can say something that builder dot has data. Alright? Builder dot has data. I'm sorry, I'm jumping the gun here. Apologists entity right there ago entity, our brackets and then we see the entities. So in this case, let's say we wanted and the default colors, let's start with colors. So the entity would be colour. Alright? And then open and close brace. And then we say dot has the, there we go. Jumping the gun a bit. Then we open and close. Well, I'm just going to open and close our parentheses within, inside of these parentheses and others that line so we can see it very clearly. We need new instances of that entity that we're about to create a new color and then we fill in the fields, right? So created by, I'm just going to say system, right? Because this is not, I used it. This is the system literarily creating Enter. It created, I'm going to say it date, time, dot null. So whenever it is, it gets created. That's the time and I'm just going to break then. So don't get too far off the screen. So comma, the next field will be data or data, which is also went to be datetime dot. No. Thanks. Guan would be name. And I've went to see, let's say block. That's a very common car color and updated by is equal to the system. So I kind of did its how POSIX nibbled. You can order it if you want or what the point is that you want to feel these in, and that should be in quotation marks as a string. There we go. Alright, I don't need to put in the ID because if I don't supply the ID, then it will automatically give it the ID and all to increment does we saw what? If I do put in the ID, then it will give it the ID value that I gave it. So if I wanted this one to be Ib ten, then I could say ID is ten. I don't want that. I want the system to do all of that. And then for every color that I wanted to add, I can separate the different models. So I just had this one created. I can say comma and then creates a model1. And then let's say this one is blue. And then we can separate them on, go on and on and on. And then this method holds true for anything else that wearable to create our seed. So I can take all of this block of code and then repeat that builder dot entity. And that said I wanted to see them make or a few mix entities. Meek dot, dot, dot, dot has data and then just say new mic, and then just fill those models accordingly. Now as again to if I do that for every table, if, if doing it for Joe scholars to go up this mode space, imagine doing that five more times for more, potentially more records. And I don't like that. I don't like my files look like spaghetti, to be honest. So what we're, what I'm going to do is kind of obstruct this into another function, right? Or another file altogether. And I'm going to create a folder here in my server project and I'm going to call it Configurations. So New Folder configurations, make sure I get that's spinning around it. There we go. And then inset of Configurations, I'm going to have a mother folder because configurations might've multiple things. So I'm going to just say entities. I always love separating these things into different files on fullness. I know exactly where to go to find watts. So this entities null, I can create a configuration file per table that I wish to facilitate seating for. So let's create a class and I'm going to call it color configuration are seed config variation, alright, color seed configuration. Now in order to get this configuration file to know about the standard that needs to be obtained with the whole builder and so on. What don't we went off to do is let it inherits from I entity type configuration. Alright, and that may require missing libraries. So Microsoft Entity Framework Core, we go ahead and include that. And then I specify the entity that I needed to know, a bowl, which in this case is color, which then was going to requirements that include another library, their goal. And then I'm going to have to implement the interface which then brings that configure file, right? Configure. Well, method's sorry. So configure is going to then inject a builder based on color, which is basically based on the same builder here for the ModelBuilder. So all of this code that I had here, I can know tic can cut it and paste it inside of this method. Now I don't need so much code and this is where I was jumping the gun because this is my usual method. And when they use this method, it's already knows it's dealing with colors. I don't have to say builder dot entity is color because it's already knows builder is based on color. So I can say builder dot has data and that's where it was. My mind was initially when I was creating the whole bit of code here. So now that we have this configuration set up in this file that is clearly not apart of the the obligation DB context. Now I need the application and dv contexts, or at least this method to know that it should be calling this configure method over here, right? So in the unwanted creating what the others say builder dots, apply configuration. And then I'm going to instantiate our color seed configuration, right? And then of course, include any missing references, and then that's it. So you see we just turned all this LAN, all these lines of code into one line of code. And to me that looks neater way. You know, when you look at application DB context, you should be able to look up the data grants and get a good idea if you want the details, you go elsewhere. So we go over here and then we see the details of what is being seated. And so that principle can carry on for any other entity that forward you want to see data. So let's say we wanted to seed into mix. What are, come on, carbons, Let's see, Toyota and BMW, right? So I'm challenging you to pause, right? Know, create your own seed configuration and get them in. So for me, So on Toyota and BMW. And then you can probably trend seed to models that correspond with Toyota and BMW models. Alright, so I hope you paused and attempted it on your own. If not, you can do that. No. But what I did was to follow the same technique. I created one for the mic, I created one-photon model, and then I have the respective files over here. So for the mic. I have two mics in the forums of BMW and Toyota. And then for the models I created four, right? I created Prius widths, which if you know cars, those are Toyota's. And then the three series on an X5 which would belong to the BMW. Alright. So you can go ahead and and you create you see the inflammation and you just create those configuration files. I mean, if you don't like doing the configuration files, that's fine. You can always just put all of it inside of the model creating what we already discussed. Why? Personally, I don't like it. So that's why I'm showing you this method. Any WHO, once we've done those configurations, we need to if you completed my sentence by saying ADA migration, then you're under trucks. So we need to say add migration. And then I can say see the default. And let's say car data. Of course, you want to tell it, it's a story within name, right? So we can go ahead and add that migration and lets us take a quick look at what that migration file spits out. And whoa, all right, I'm getting nasty error. It's good for us to see these errors because we do run into them from time to time with our migration. So it's good to understand what might've gone around. So it says the seed entity for entity type color cannot be added because nonzero values required for Property ID consider providing a negative value to, okay, but then looking at my seed configurations that don't have any ID. But then I'm wondering now if that comma on the end is this system thinking that I meant to put in an ID. So let me just take o.com. I don't know if you have this problem. If you do, then you could try this also. If you don't, then kudos to you got it right the first time, someone to try again. And there's also a troubleshooting process. Well, that did not help. So what I'm going to do then is try and be explicit with the id. Alright, so one of the advantages to being explicit with the ID either way would be that if we were creating records that C had dependencies. So I will seeding in default vehicles for instance, and then add to put the color, I'm sorry, the Caller ID and the Meek ID and so on. Then by being explicit with the MC and the whole IDs are all the IDs in these entities. Then I can explicitly say that the vehicle should have this caller ID, this Meek ID, because I know that by default those IDs should be present. So let us put in those IDs. And chances are you're probably gets into same era as me and that's no problem. We can see exactly what the error is on hold. Solid. So putting those ID values in color, make, and model. Let's try again And this style. And there we go. So we get to our migration. So no, we see, alright, so yeah, I misled you a bit. We have to put in that id value from the get-go. Alright? So our migration file would say insert the colors and then it's puzzle the columns. And then it gives us the values that will go into each column. So ID, ID system, new datetime for the created. The same thing for date updated and so on. So it does that for all of the tables for which we had specified seeding, see that data, right? And then the dawn of course reverses that. So when we do update data base and then run that. And then in the meanwhile, what I wanted to do just go to the server Object Explorer and refresh. And we can just take a look at the data that is now in our colors table. So if I right click and say view data, then we see our dataset ACR IDs, even though there will be generated automatically when we are on the system is being used by the users. We are seeding, we have to provide those ID values, which makes sense, right? So that's all we do for colors. So if you want, you can try and seed some data for a vehicle, for some default vehicles because we already have make some models. And let's say we start off the fleet with two vehicles. I'm not sure I want to necessarily seed vehicles into the system though. I'll probably want the user or whoever will be using this obligation on a daily basis to actually do that. But one other thing that I do definitely want to seed into our database would be rolls, because we're going to have different roles in the system, are going to have admin user_roles, right? So let's just do the rows and then we can call it a day for this operation. So, you know the drill I'm challenging once again, go ahead and do it yourself and we can compare notes. Alright, so if you boss Don, you attend teeny-tiny got stuck, that's no problem. And I'm here to help you through it. Alright, so the thing with the rule is that I did say roll, but the datatype required is not rule just like, oh, you have identity user for the users, you have identity role for the rows. So our role configuration file would have identity rule as the context or as the entity, right? And then when we're building all we have new identity rule and we have name and normalized names. So this one we don't, we definitely do not need to put an ID because the ID for our ASP net tables would be GUID, right? Which means it's, it's hard for us to put in the ID there we could, but we don't have to add this point unless we were going to see the users who will hover was, we needed to explicitly state the id. Then we would say something like id is equal to dot new good dot toString. So it would generate an explicit GUID and then put that, but then that's still kind of random because we're really still not sure what value this would provide. So you can actually go ahead and get that good somewhere else. You can find that online and generate a GUID. And you just put in that good Valerie or self. So then you know that this is a good value for the user role. And then we could say that this could slightly modify, that would dissolve to be any big modification, the stanza four to 56 to it, and it would be nothing too fancy. C, C T, T, T, T to F, F, right? And then that's our good. So then we have Tomorrow's, we know the IDs. So if we were to use how to use them later on, we can do that. So I'm just showing you that there are so many dynamics existing way fewer early done Arab doing it one way, then he can try it another way and we can work our own accordingly. So now I've added these roles. I need to add the role configuration here. Right? So that when we add a migration once again, and then this one is C. C the roles are default rules. Then if we just take a look at it, we'll see here it's adding us the roles. It's going to be doing all of that. And then it still sees the configurations here, but it's not making any updates. There's nothing there to be updated to tough, right? So we can go ahead and update our database. And then when I go over to my database and view the rules, I'm no seeing them with the very ID values thus provided and the data accordingly. So that's just a quick introduction as the whole weekend sets up some default values in our system. For when our application is installed, the users would have something to start using. Something like rules definitely will have to be in place. Because when users are registering are being created, we need to assign them to are all all, all tough the box, right? So it'll be good if in your own time you go ahead and seed in default administrator, user, right? Anybody we're just says we'll need to register as our regular use of later on. We'll look at that though. But right now you want to focus on at least getting in a default administrator users, so you create the user one. But in ceding this one, you have to see the user Andy off to seed the user_roles. Alright, so you can go ahead and do that as a challenge. 15. Seed Default User and User-Role - Compare Notes: Alright guys, welcome bug. So as I'm sure you inferred from the title of this lesson, it's really just to compare notes because I left you with a mini coding assignment and I hope you attempted it. If not, then the school story together either way. So the assignment was to make sure that you see the user as well as the user role. Because what we want is that default user with the admin role in our system. So I created a configuration for the user and the configuration for the user role. So we already did the roll together are the roles where we had or identity role we created our own good values are set the IDs explicitly. The thing is that of course, if you have dependencies, you still want to put in data in the order of the dependencies. So the same rule that's applied or that I would have encouraged when creating the tables. It applies when seeding data Cozy Car B, seeding, a user associated with our role when you don't have the rules, are the users, alright? So we have the role. We created the user. So I have the user seed configuration where I set up a user. And I mean your user might be different than if you had difficulties with this stuff, then no problem. That's why we're here. What happens is that I had to use a harsher. So we have didn't library afforded to us by the identity core libraries called the password harsher, and we contextualize it to the application user. And then with this hoBshare weekend, create the hashed passwords. So I'm just initializing that. Then we said builder has the, it'll create a new application user with the explicit ID, which is just another good, the email address, the normalized email. So email and normalized email will be the same except normalized means everything is uppercase, right? We give it firstName, lastName, username, normalize username, same principle as the email and you normalize email and then a password hash has to be a hashed version of whatever password. So this is a default boss or that we're using. Sure. But we can't stored that text in the database, but we can sort it into source code because our clients probably will never see the source code. But then in the database level, we should never, nobody should ever be able to go into our database and see that processor. So into different word, sorry, identity core with always hash the password. And so when we're sitting, that's what we have to provide a hashed password. Alright? So we provide that hush buzzword and that's the user. And then in the user role configuration, same cephalopods we just went through except we're using identity user role and that has to be contextualized to string. All right? And then what we're going to be putting in here, we don't need the ID here, but that'll really, I don't think that thing is stable, uses an ID, but we do need the role id. So I went over to the role seed configurations and make sure I got the character ID, which I had on top. So let me meet that courage on right, and all administrator, alright. Id that we need is the administrate, the one. There we go, and then the user ID is wrong, all sorts. I'm just showing you, make sure that you get these correctly. So the user ID to be used is this one right? So after we made those corrections are I mean, those axons cuz I'm sure you are already underwrite truck. Then we can go ahead and seed our user defaults, right, so updates, Database. And sorry, we need to add migration apologists. So add dash migration, right? And then we say added default users. I load that migration to run. And this is the second time that we were seeing this yellow strip. If you read it the first time, I didn't point it's old but it's basically saying that there's some scuffled and that might result in the loss of data. So I did allude to that earlier when we were discovering how migrations work that sometimes you meet changes that might affect the existing data. So you'll get to, it's a warning to say, hey, you know, be careful because you might be erasing data. Just give a quick review just to make sure that salty really wants. That's all it's seeing. And these migration files as we see, we can always modify them if we want, right? So here we're seeing inserts into these tables, these values, no problem. And then we know that the next point of action is our update, which then should give us some default users. So we already registered I user. And so when I look in ASP net uses, I should now see two users. The one that we registered, right? Remember test at blazer.com, That was the user that we set up initially. And here is the one that we just seed it into the database, which is our admin user. Alright? So you see that that is working and then we didn't provide a first name and last name when we registered the user because well, we need it, we'll need to modify the registration for that. But then we have the admin user fields here, the firstName, lastName, according to what we see that which of course they were optional anyway. And then if I go over to roles, we know that we're zeros. Well, let me just focus on the user roles table where it will show us which uses associated with which role. So like I said, it doesn't have an id column anyway, right? So we just wanted to know that this User ID, which is our admin user, it E for, for it, E for, for their low corresponds with that rule. So that's basically all there is to seeding default rules, default users into our application. 16. Review and Add Changes to GitHub: Alright guys, so we're here and we're at another checkpoint and we're just wanted to kind of review all of what we did for this section. So firstly, we started off looking at our identity server identity core allowances. We reviewed what is in the startup file that allows us to actually connect to the database, as well as connect to our identity server and all of those features. Then we went into actually setting up our own database scaffolding notes, the identity server tables so that we can store users under roles and all those supporting bits of data that went into creating our own domain models and adding them to the same database. And then we went ahead and looked at whole weekend seed our creates some default records in our system at runtime. So after doing all of this, I'm sure you would have absorbed at all and he can always don't and review it and try and get it, concretize how everything works, what's at this point, we just want to check in our changes to our repository to make sure that we keep a nice quick account of all of the work done. So what we do here is go over to get changes, and then we give it a nice little commit message. And this message, of course, should be clear enough to, you know, yourself in the future or your future self, as well as anybody else who might come and look to tell them, you know, what exactly was done. So you can always just scroll through and see all of what happened with scaffolded out our identity pages. We took a look at the seeding configurations, all of these migrations. So the cool thing is that if anybody else comes after you and gets what you're about to check in this quote, old software repository, all they need to do is modify, maybe they're up settings.js son to any database server and database name that they wish to have. And then they are an update needs a base. And then it will automatically goes through all of the migrations and apply everything in the same order that it is lined notes. Alright, so if you lose this machine that you're working on null, but you have a copy of your project on GitHub, then at this, at least at this point, you haven't lost any data because all the data is just default stuff captured in these migration files. So you just need to get this project out that snapshot where both the chicken and then you run up my database. You will go ahead and create the database, putting all the tables and the structure and the big data for you. And then you're at but got square one. So right now let's just go ahead and say commit all and sink. So that miserable committee locally and it will synchronize it with good job Stacy committed locally. And then it's pushing and then it successfully synchronised with our GitHub repository. So when we come back, we'll continue learning more trouble TO this whole blazer application works with Entity Framework on all the moving parts. 17. Section Overview - REST API and Database Access Setup: Hey guys, welcome back. In this section of the course, are going to take a look at how rest APIs interact with blazer. No, I had alluded to this interaction before and I'm just going to give a quick recap in this overview where we'll take a look at one, the fact that the server project is really an API project. And what we'll be creating Ruby API controllers as we see here with the sample weather forecasts controller, where we have an API controller and what it really exposes our endpoints. So if you're not too familiar with rest APIs, you can look at my Although courses on rest API development with.NET Core Five, or my end-to-end blazer and Web API development course, where actually taught, talk about building the API as a separate entity and building clients to connect to it. And these clients will be blazer clients. However, in this particular course, I won't be focusing too much on Rest, API and all of the practices that go. And I just really want to assure you that when you have this project templates and you want a blazer application, you're going to end up with our client application that we've seen server application and how we're going to build out the API functionality to serve this client. So everything here is internal to one big application. It says that it does some moving parts and I just wants us to have a full appreciation of all of the different touch points and how they come together. So when we come back, we'll continue our discussion on our API controllers will create our own and see exactly how we can test it to make sure it's working. And then we'll move forward from there. 18. Create and Test REST API Endpoints: Our guys, we're back and in this lesson we're going to look at creating, anticipating our rest API endpoints. Alright, so we already established that or endpoints are exposed through what we'll call it an API controller. And once again, I'm just using the weather forecasts controller as grown 0 because that's what we're given. And we see here, If you're used them VC, it's really just another controller just has this annotation to specify that it's an API controller. It inherits from controller base, but everything else is pretty much the same. Also over the axons, we treat the auctions nor like endpoints, and we have what we call the rest verbs. So RS verbs will be get, post, put, and delete. And either way, these are generally the crowed operations that we're used to, right? Get would be read, post would be create, put would be Update, and Delete is delete, right? So these are the verbs that help us facilitate our crowed operations. Now in the, in terms of testing our endpoints when we run our application here. We know that we get our web interface, right. That is what we are presented with and that's fine. But then we all, we already established that both the client and the server applications are running off the same address here, which is localhost colon 443. If I've in my case you, you'd probably have a different port number. But the point is that both the client and the server application, they're using the same address, which then means that I can use my API testing tool called Postman and pleased that same address in a get request. And then what I wanted to test is if I can get the weather forecast data, right. So it does say get. So after make sure that my request is I get. And then the way to get to it would be through the root controller. And controller either means the name of the controller, which in this case is whether for crop forecasts, sorry. So then I can see HTTPS colon localhost colon, colon slash, slash, sorry, localhost colon, the port number, and then the name of the controller, which is weather forecasts. Then when I send that request, well, in this case I'm getting back a status for 01 on authorized why am I getting that buck? It is because we have this authorized annotations, so you have to be a logged in user and everything. And we went through the whole identity flow and everything. So if you're not a logged in user trend to access this endpoint, it will reject you. So if I just comment this out, not authorize and retry, then I'm going to get a different response where I get a 200 OK and I am getting back the data from the database. All right, so that is whole and API works. I'm getting about this JSON, and this is the JSON that's going to, well, this is not coming from the database first and this is all somebody that was baked into the, into the action or the end point. But let us just represent OS running a query, getting the data and then sending it back to whoever is requesting the data, which in this case could be lost through Postman or our blazer client-side application, which is why in the client project. Now see in with the page's fetch data, they will go and fetch data. It did that same operation. It went and it said, I want data from this endpoint. So I don't want you to look at this code just yet. I'm not showing you that that's what this speech for, which data is doing. You weren't able to access it before because it has the author I start. And at the time we didn't set up the whole user login system and so on properly. So now you can actually go and test it, but this predicts the client-side application. Whereas this author as odor, predicts the endpoint from unauthorized access, but then through the Integrated Authentication in our application so far, then we are actually able to just authenticate on the client side. And then this author I start, we'll see that it's our, it's an authenticated request coming through the client to this end point, so it will allow it to interrupt. So I'm just giving you an overview of what obtains in the sample. Nowhere going to create our own. So let us create S1 and a simple one. Let's start off with one of our simpler tables like me. All right, so we'll want the endpoints for to allow the client to be able to interact with our database table for me. And the client is going to do that through the API. So the API needs to be able to communicate with our database. Now the good thing about Dante corps that they give us scaffolding so I can just right-click go to, go to new item. And then I can choose that. I want an API controller. I'm going to choose three, right? So I wanted to go to controllers, go to Add, and then say controller. And then I'm going to get this dialog box asking what kind of controller would I like? Well firstly, I want an API controller and then I want one with actions using Entity Framework. No. I went to build it within two different work. Walk you through the code and then kind of explain why people would implement other patterns on top of the Entity Framework so that minton abilities easier in the long run. But to get up basic application that can read, write, and interact with the database and the client. This is all you really need. So API controller actions using Entity Framework, we click, we give it Doyle who have to specify the model class. So the model class here means which class it doesn't really nor curable the clouds is which one is domain are not. Of course, we have the responsibility of making sure we choose the correct one. So I want one for meek, right? The data context class would be application on DB context, and then it's all degenerates the mix controller name. You can change that, but I think it's clear enough what this controller will be forced to leave it. And then I went to go ahead and click add. And then after a few seconds and some buck grown Ward, We will now have our controller. So you'll see here it has the root API slash controller. If you compare that with weather forecast, this one doses controller. So the difference is that we can actually specify the route. So I don't want it to say api slash, I wanted to just say control. So in other words, to get to this controller, to this roots, we just need to see makes, alright. It does give us annotation API controller. If we want to make it protected, we can add the authorize annotation at the top, which we won't do just yet, so I'll just put it there so you remember to do it later on. And then the rest of it is really just saying that, okay, we have a class with that name inheriting from control obese, we have private read-only application DB context, and our object is on the score contexts. And then what is happening here is called dependency injection, where we're injecting the application DB context that's serving the entire application on the entire API, where injecting it into this particular control and making a local copy. And that's what's happening here. So we make our private field. We let the constructor nor that it should expect up, you know, the, the object of the application DB context, which represents our connections to the database. And then we want to make a local copy. So we equate or local field to the objects being sent in, and then we continue our operations with our local field. Then you would notice that we also have all of these verbs kind of generated for us. We have the HTTP Get verb, web, HTTP Get with the ID specification and then they can I give examples. So NSA slash mix. So it says API slash mix because by default it's an API slash controller. We took off the API slash Cyrillic and surely what we should have is just mix, right? Those are comments you don't have to go through unchanged and I'm just explaining why we will take it off, right? So when you hit mix, it's going to hit the get by default. And then it's going to then call this method. So the end point here, this method is really just a method that has whatever action needs to be carried out. However, the function name or a method name is not what we're putting into the path. All we have to do is call this because then it will infer that when you meet this kind of quality, you are making a get request. And so I will call this method automatically. Alright, so then you'd notice that this one would get the same method name except it takes a parameter of type ID and are expected to disperse into ID that you hope to get to. And it carries out all of that operation. The same thing with put method name. It expects that ID and expects data to card 22. What should I see a company this ID? And I'm not going through too much of the code just yet because we are going to be doing a big refactor with this. But I'm just pointing out that all of this will work out of the box. So what we're going to do is run this and testing. All right, so we're back in Postman and I'm going to change this to say mix. Now remember that we had scaffolded sum. Mix into the database initially. So that means I have data that should be able to come back when I send that request. There we're getting Bach or data or getting about Toyota with the ID1 created by albeit it by all these wonderful things. See, all of the data is coming back. Just in case you're here, think it's not really working on trend to drag the STM when to put a breakpoint here on this getMethod. So let us try this again. I click send and then Visual Studio's going to alert me that I have hit the break point on this method, which will then run this query database connection, get me the makes table and put everything in there to a list and return it. That's pretty much always doing. It will automatically serialize it into JSON block of text and send it back. You've wanted to test another one. Let's say we wanted to test the Get with the ID. Alright, so I can say mix slush tool. And then that should bring me back only the BMW objects because then the method said, go to the database and find the record in the mix table that has that ID. And then if it's if it's not if you didn't find anything returned, not phoned, otherwise it turned the Beatles. So if I put in ID Tin those, I don't have ten mix into database. So then it returns, not phoned this if statement and it returned not fold since he, all of that functionality came out of the box. All I did was click three or four times and we have a whole controller. And the fact is that you can generate these controllers for all of the functions, all of the other tables and endpoints that you need to expose to your client so you can go ahead and do all of that if you want. Just to explain what those put takes the ID and it takes the data for the mic, meaning I'm about to make my boat to update some things off to send over the object with the updated data. It will make sure that the IDs match. Otherwise it will return an arrow 500 or bad request. Then it's going to say, okay, database, look for the matching record are based on the ID, the record in the database snow, and then change its state to modify it and then just save the changes because I just got updated data, so NOR that is modified and in CVE, whatever changes there are to the existing record. And then this is erupt in a try catch just in case there's conflicting our conflicting attempt to update the same record. That's pretty much all that's doing. The post is the Creates, right? So when we're making a post, it means that I need to change the verb. So the verb in Postman needs to be changed are coordinating this, I'll change it to post. It'll be the same slash Meeks. But then the body. And what I'm going to do is just kind of take one that's already had. So I have to provide data similar to this in a post request. So in the body. All right, I'm going to say I wanted to possible overall JSON and PS dot there. This time I'm going to put in a Honda. So that's the new mic. And this Honda's went up ID3. Well, actually I shouldn't be providing the id. So at this point, I don't provide ID because I am actually creating something into the database. So the database should be responsible for its own idea dot points, right? So honda created by analysing a system just the same way because we're not quite ready to see the user who is logged in is doing the operation, leave the timestamps that audit stuff. So right now we can get away with that. And what I will do is submit this post requests. So this should send me back the object that was created. There were loans, so it's it's full on created. And it's showing me that Honda was created with the ID3, with all of that data, right? So this Endpoints is database, Get me the table and add to it whatever object is coming over through our request and see if those changes. And then return created_at action, which is the tall one. And say you can go to get me with that ID and that's the object. Pretty much. All of this is what gave us this return, this return result. And if I go here, location, if I go to headers and look at the location, that's what didn't buy created at auction. So that means it's sedentary where I can go and get the details, right. Delete works. Similarly, once again, I just have to pass in the deletes. What I would do is say mix and let's say two. But then delete. So here's what I'm going to don't want to create that dummy car. So dummy car. Alright, so I'm going to send over another post requests for our dummy car. Let me send though MCAR with ID four. I realize, oh no, that was a mistake. I shouldn't have done that. So I go back, go to delete and I'm going to change the verb to delete makes is for ID for. And then when I send is going to say tool for no content. So anything that's a 200 code is successful. And then, you know, it may vary. Anything that's a 400 is, is relatively unsuccessful, generally unsuccessful, and 500 is definitely not successful. So that tool for no content, even though it says no content and it might look like a negative response if you know the rest verbs and what they mean ADA risk responses rather. And what they mean, you'd see that tool for is actually a good response. So what we're getting, what we're doing in this delete method is where finding it. If it's null, then we, if it's not, no, sorry, then we remove it and then we save the changes and then return. Not good results. So pretty much that's what we get out of the box for our controller. Now, as I said, it's simple enough to go ahead and scuffled these kind of control for all the other salvaged for me. So I can go and do it again for our models. I can do it again for vehicles. Again, do it again for all of them. The problem, whoever comes in when maybe there are certain customizations that need to be made. When saving changes, I may want to do something differently. Or other basic operations I may want to include at 1 and not include. That's another point. There are certain things that make maintenance difficult. As our obligation expands when we just use the alt off the box code, as you see here. So what we want to in the next lesson is implement a pattern called unit of work, where we abstract this, all of this database operation from the controller directly. We won't directly interact with the database from the controller, but we're going to put another layer in between that allows us to orchestrate what's up, ends up at Nitobi HIS level. You know, it's a bit more scrutiny and more generically. So don't tough to strongly type all of these things all the time. And then we can see where maintenance can become much easier in the long run. So I'm not one to scuffled any other one just yet. I'm going to go ahead and put in the unit of work and then we can scuffled, arrest and implement the unit of work functionality in those one time. 19. Implement Unit of Work: Hey guys, welcome back. In this lesson we'll be implementing the popular coding pattern called unit of work. Know, before I go into the unit of work Potter and I just wanted to point out that while I'll be showing you the pattern and while I do encourage you to learn this pattern, this spotter and might not necessarily be necessary for you on your contexts. Because like we said, and we already established, we could easily with a few clicks, just generate the controller that already has a connection to the database and allows us to manipulate data, tuxedo data, everything from the database and our application accordingly. So within your context, you might not need to go as far as implementing this kind of pattern. However, when you're thinking about scale ability and maintainability, readability of the code and not repeating certain critical libraries all over the place. And having to make too many changes every time you want to do an upgrade or a modification, then you start thinking about patterns. So my weapon of choice when it comes to data access, patterns would be the unit of work because it allows for a very generic implementation of basic crowed operations across multiple class types without having to get too specific with the quote. The more specific your code gets is the more maintenance you have to do when something needs to be changed. So when you can keep it generic, then it's good. So we're going to be implementing the generic repository Potter and as well as the units of work pots are. And on top of that. So let's get into it. So for this, in the server project, I'm going to create two new folder. So I'm going to create one and I'm going to call it I repository, which is going to store the interfaces. And then I'm going to have another one. I'll just copy and paste and rename that then went to call repository. Alright, so we have two folders, one to store the interfaces on, one to store the concrete implementations. So the first interface that I'm going to have is the, is our class. I'm just going to create it as a class without goning to add generic repository. So you can say class or interface. If you do interface, remember I have to change it to public. If you do class, then remember you have to change it from glass interface. So I generated just do the class and then change it because sometimes I forget to me the interface public anyway. Alright, so let's talk about generics now if you're new to the C-sharp, maybe seven or it, generics were introduced. And I've generic allows me to specify, are not tough to specify or other class name. Alright, so I want this repository to have functions that will allow me to interact with multiple classes. And when I say class is I mean these data models, right? So this generic repository, he's going to take a key of type T. And then I'm going to specify that t is going to represent our class, meaning it can't be anything but Dr. classic found best stroke Darren interface or anything, you test the back glass. Then inside of this interface I'm going to specify a fuel functions, right? So I'm going to. Of a function that's going to allow me to get, all right, and I just typed it told you can pause, replicates its on their own, right? But then I'm going to explain each line anyway. And this is really just one method with all the parameters I just wrote the line because I didn't want to go too far off the screen. So I have task. We're returning an Ion list of type T. So T, that generic, whatever data type is passed in, that's the type that we're going to, that's the data type we're going to be focusing on. When this method gets executed. It will call the method get all. We open parentheses, our taking Parramatta number one, which is an expression, right? Which is really just a lambda expressions. I'll go ahead and include that. So I'd taken a lambda expression as bare metal one, where taking an orderable query as parameter and then a list of string called includes. So we may want to get to all parameters. I always saw that we have different relationships between our tables, right? So it could be that we wanted to get all the bookings and go on to include all the details of the vehicles and the customer per booking. So we would have to make sure that we include the additional data. And I did mention earlier that that kind of implied inner join is available to us through the right. Next up, we have another task. And notice I'm using tasks. So this is a part of asynchronous programming. We'll see more of that when we're implementing the methods, we have another task of type T. Alright? And we're getting how we still have that expression. So the same type of expression, but this one is not nullable. So this one says that you don't have to pass in an expression. If you go on to this one, if I'm getting, this is representing one entity, then you have to tell me which one you want. So you have to give me the expression, all right? And then we allow the list of includes also. And then other methods will include and others put them there and walk you through them. Or insert T entity. Right? So when we want to add to the database, we call our insert method. We can insert list of entities if the need ever arises. We can delete one based on the ID. We can delete our range bossing in all of the ones that we want to delete. And then we have update t entity. Alright, so that is our generic repository. No, we need to have the concrete class for our generic repository. So we're going to go over to repository, not ire repository at this time, but repository are going to add a class. And it's actually a class system. Where does giving you this same name just with all the I0, I0 generic repository and then generic repository, we click add. And then we have to let this one also be generic. And it's going to inherit from I generic repository. Alright, which ofcourse is of type T? Sorry, did I build inadvertently? And then we do the same thing where we say where t is glass. I'll just copy that because we just wanted to be a very explicit but then I need to include the missing Reference Board that after including the missing reference will have to implement the interface. So go ahead and do that. And then you'll see that it's generated all the method's stoves dot correspond with the methods that we had all lined. All right, so let's get to work in our generic repository. For this section, we need to inject our database context as well. Initialize our DB set to whatever data type is passed in St. So I'm going to create my own local field privates read only application DB context. So after this one naught context, remember that dot represents our connections at the database include the missing reference obligation on DB context, and I'll just call this one on the score contexts. All right. In addition to that, I'm going to initialize another private read-only where I have db sit. That keyword rings a bell to you and TV set is of type T. Because once again, I don't know what t is going to be at any given point. I'm making this as generic as possible and I'm going to call that underscore DB. So I need to include a missing reference here. That's fine. And then I need a constructor format generic repository so I can write the keyboard shortcut CTO for stub twice and it generates that constructor stop for me and then I need to inject. So the same way that we saw that injection hub bandwidth makes controller there it is. That same kind of injection we need to inject this object into the generic repository. And then I'm literally just copy on basic laws is the same quote is the same concept we need to initialize or local copy to the injected object. And then after that, I'm going to initialize my DB objects RDB field to be underscore context dot set of type T. So in other words, DB knows when to represent connected database set of type T, whatever t is going to be at the time. That's a method. So you put in your environmental department does and close off. That's his or settled for generic or bluster. So anytime this repository is going to be initialize, is going to injecting that connection to the database. And then it has to be initialized relative to a particular class. So then it's going to say, OK, I'm connected to the stable. And then we're going to see when these methods are called, are called into action. What should happen? So let us start off with the simple ones. Delete is very simple, is actually very, very simple because what we need to do a one is find the entities. I'll say var entity, or I can say var rect card is equal to. And then we're going to start at a can't asynchronous programming in a bit. So when we have, when we're working with Entity Framework Core, they give us a bunch of asynchronous methods because if you just say db dot, you'll start seeing add async, Iberian JS sync. All of these, most of these have an Async version to them. Whenever we're going to be doing something that is asynchronous, we have to precede that call with the keyword await. Alright, so I want to find a, find a sink, and I'm not going to find when I can find a sink, right? The difference between the two is that asynchronous means that D kinda run on different threads. The obligation on tuft will stall waiting on the results of this function calls. So that's what the AC, that's an advantage that the asynchronous programming brings. So I'll just say find a sink and then find expects some objects. Well, I'm going to pass in the ID. So like we saw in the main scope controller is the same kind of logic, correct? In the delete, it had to find the record. And then it's going to call that remove, right? But then we're not going through as many steps essay in context that makes this, we're not being this explicit because they're being generic. So EBRD embodies whatever was passed over, Find it asynchronously storage and red card. And then I'm going to say on the score db dot, remove this required. So there's no async corresponding function to remove. So that's fine. I'll just user move. And I'm going to say remove the record. No, notice that I've read lines. One. I need oh, I did say that we need to precede this with await. Alright. So we have to say, oh, it's noticed dot-dot-dot goes away, but then this one appears because once we're doing an await, the method has to be a sink. So once you're making an asynchronous call and you're going to have to use the keyword await. Makes sure that the method making the call has the keyword async. Notice that both light up when I highlight only one. Alright, so there we go with delete. Delete range is well, fewer lines of code because I love to see is honest score db dot remove range. And they remove range is expecting a parameter, a collection of whatever it should remove, which were passing over in the form of entities. Alright. So that's it for delete. One. As I said, I'm dealing with a low hanging fruit. So this one can get wordy, this one gang get wordy. So let's jump down to insert in surgery in general updates on there we can backtrack. So insert is relatively simple. All I have to say for insert is a weight d, b, add async and entity. And then once again, if we're using a weight, I have to make sure the method is a sink. If we're doing the insert range, we have similar code except it's every inch blood that one has a seeing. So at range and once again, a sink. Alright, and then for a bit, what we need to do here, so for the update on this side, what it did was that me find or did it just said that entropy changes state to modified, alright, and then save changes, and that's fine. Alright? What we can do on this side, what I am going to do on this though is slightly different. Well, it's one extra line where I'm going to say underscore DB dot-dot touch entity. And the reason we're doing this attached entity part is that when we do the get, they get all where detaching from the database. So basically in mix, whenever a query is don't are these entities are being thrown our own, they're always attach, the database is always still watching on tracking everything that this object is going through, which can have some performance implications when you have thousands of records that into different markets trend to keep track off at all times in memory. So what we're going to do is when we, when we do the get's, we're going to say no tracking, which means that they are detached. So when I'm about to do an update, the reattach this entity. So the database to the collection. So then it starts trucking it. And then once it's trucking it, No, I can see that entity entry. Whatever entity is our context dot entry, the entity being passed in that state is equal to entities, states modified, which is the same thing that was happening here. Once again where being generic so we don't specify mic because I don't know if it's on me, give it some model. If it's a vaguely resembled Can we don't know. So that's why we're being very vague with our names here. I'm calling it m entities as opposed to me can model and anything specific node. Let us backtrack a bit and go up to our Git and get all. So get to, get is easier. Let's start with Git. So the first line off to get is to initialize a query. All right, so I queryable tea, and I queryable is a very specific datatype, which means, which basically represents the first datatype you're getting when you interact with the database. And from here you can kind of carry out certain operations more efficiently against the database collections than you could if you had a list stored I enumerable or something else, right? So we're initializing our query of that BB. So right here, all records are loaded into memory. And then I'm going to see if it includes. So we would've passed in includes. Includes is not equal to null, which means that something was sent over in this list. Right? Then we wanted to see if for each, i can just do that and say tub, tub, var. I'll just say in, let's say prop. Let us use a word prop in The includes list. All right, then we wanted to see query which represents the database connection. Are the database queries equal to query dots include? And then I'm just going to save prop. So it's undisturbed string, all you really need is the name of what it should include, so we'll seal that works later on. No problem. And then after all of this, you'll notice this is, is read. We need to return a query dots. And then I wanted to see as more tracking. So here's where I'm seeing detach from the database. But I want you to return the first our default and I'm going to choose the async version of that method. And then I pass in the expression. Alright, so if you're not familiar with lambda expressions, well, lambda expression, lambda expression is what would have been setup in here. We boss it through, right? So you can see on some bluff lambda experts on here in this mic exists method where we say contexts dot, dot n0, and then this is a lambda expression. So it's that kind of expression or this kind of value that will pass over in this method. And then it will carry out that operation. Right? Now, of course, I did see a sink here. So that means I need the keyword, I wait. And if I need the keyword o h, that means I need to make my method here a sink. There we go. Alright, so that's the get Juan, Juan record, right, based on this lambda expressions. So it could be by ID, it could be by name equal b by year. I mean, I don't know. It could be the vehicle by Vin vivo looking above ICO by Vin, you know, just make sure that we put in the appropriate expression to make sure we get back the value we're looking for, right? Four gets all null. We actually start off with the same fewer lines of code. So I need the, well, I need the query first off, right? And then I'm not sure if I'm going to get to an expression, so I don't want to go ahead and try it out, play an expression, especially if it's null, that will give me an error. So I'm going to see if the expression is not null. Try that again. If expression on, if they will go express on is not equal to null, then I want to filter the query. So remember this represents all the tables in the database. So I'm going to say the query is not supposed to be filtered by the expression. So we don't all of the ones that we know we don't need if an expression was given. So if we said give me all the vehicles that entire block, then we're passing that to give me all of the black one. So all vehicles that would filter down to the ones that are only block. And then. Based on the field. And once we do the same includes, so I'm just going to copy that block here. So if he includes, then we go ahead and include the details that we needed. And then we also have the order by let me just bring down all departments o so we can remember them. So we have the expression, then we have the order BY. So after including, then we can go on order. So we're going to say if order by is not null, then what we want is Query being equal to. And then we have this method order by query, right? So rabbis really like a method and it's just going to rearrange them according to what was specified. Then at the end of all of that, we just want to return query dots. Once again detach them from the database dot told list. And I'm going to meet that one async, if it's a sync, I need to await. And if I'm waiting, then my method needs to be a sink. Alright, and there we have a generic repository looking good so far right? Now the thing with the generic repository, while it is a generic, yes, we're still going to have to kind of instantiate it every single time where it went to interrupt with that different table. Which means that if in one control law we might need to interact with multiple tables, we'll need to instantiate it multiple times. So I'm going to put on another level of obstruction. And another thing that's missing is the Save Changes. So another level of work is going to go in. And I went to implement that in the ire repository folder. And I'm going to create another interface. So let me just create this as an interface is time, and I'm going to call it, I need a fork. And once again, remember to make it public. Now this i unit of work, I'm just going to inherit from disposable because what we want to happen is that when you finish using the units are force, it dies in memory. We don't want to persist it through alter it. So that's fine. But then what we can do in this section, null is actually kind of created like our register for all of the potential implementations of the generic repository so that we would only have one would only do it one time well enough to do day every single time you have to interact with multiple tables will only have like I register one time. So I would create ij generic repository for me. For instance, give it its name. So I'm going to call it mix some people. If you, if you have a look at this pattern, otherwise he may see some people call it that makes repository to be very explicit. But once again, that's just the NIMA dot point. But the class is what's really important. So I'm seeing implement a generic repository for our mic, right? And remember generic repository required class, Cool and then mix. So anytime we call IU tough word mix, it's going to automatically implement this. And it's automatically going to go through this connect to the database. And Connect that table. Alright, so we can do that for all of the tables really. So we can say model. Again, see vehicle, all of them, right? When we add a new table, I will have to have a new repository. We'll just add it to the register. We don't have to go through all of this again every time we have a new table. So you can go ahead and add all of them. But for now I'll just work with the ones that I just work with me. Activate those needs be cause we have the mix controller, so I'm just going to work with me and show you how that refactoring will happen. Alright, so after that, no, we need concrete class for our units off work. I'm also going to implement task save. So this is going to represent our Save Changes and whatever other operations on it is that we may need to carry out a twin where saving. So let me create the concrete class nor for the unit of work. So I'm going to go back to repository, add a new class, and I'm calling each unit off work. So I unit of work and units are fork create that this is going to inherit from IU and it's all fork. And then of course, in the same fashion as anything else inherited, we have to go ahead and implement or interface. Alright, so here it's going to try and initialize the generic mix, right to tha's the dispose method being created because we had the inheritance to the dispose, and then we have the save method being generated. So from here I'm going to do a few things. I'm going to have the same kind of read-only that we had for the context. Someone to create that application DB contexts reference here. And then I'm also going to have a private version of this public repository for me x. So let me just do that. So I'm making private read-only. I engineered repository mic, but then it's private so fully in that keyword or that naming convention rather I'll just call it mix, right? I'm also going to need a constructor. So c bar, alright? And this constructor, if I'm expecting to use this, then I am definitely going to have to inject in the object, like I've done prior to this. And go ahead and instantiate it, our initialize it to the injected one. There we go. Alright, it's all of this is called dependency injection, once again, standard procedure and it's made very easy through dominate core. So let us focus before I focus on the spire, let's focus on what happens with the dispose, on what happens with the Save. So in this pose, what I'm going to do is say, firstly, get me the context and dispose of it. So whatever local copy of the context I'm using when the unit of work is done its work, just dispose of it. And then I'm going to also call the garbage collection and see suppressive, analyze this. So this units of work object kill it in memory, but that's pretty much what's happening there, right? For the save operation, I'm going to say, I'll wait, contexts Save Changes async. Alright, well of course that's our weights, so I need a sink. Know what's happening here is that we can, we have the opportunity to actually put in more things into our save operation when we have this method, right? Because we do have where we want to do last updated and created by an all those things. Imagine if we add all of these controllers, just built like this. And then every time something happens, not get like put like an update. I have to remember that. I have to say meek dot update the updated date-time, no dots of beta bys equal to whoever was logged in. And I have to do that religiously, right? And often do that all over. If I have ten controllers out to do it in Alton controllers, if something changes, a field changes, the name changes are something after. Remember to change it ten times. When we have the opportunity to put all of that one place, it brings a major advantage because here I can customize this method to make those adjustments before I save the changes. And so I do it one time. And that's the power of a pattern. But we're not quite ready to get there yet. What I'm going to do to finalize this video is show you what is required for this line. So for the public method and easy way to kind of do this initialization is to use a lambda expression. And then we will use that. And see on the score mix was the private version. Score makes that spreaded fors onto this. And then we're just going to see if it isn't null, then it should be equal to. So this operator just means if it's null, then make it equal to. And then we're going to initiate a new generic repository of type mic into that object, right? And then we're going to pass in the context that was initialized here. Alright, so that is what that bit of code looks like. And oh, this shouldn't be read-only apologists. So that should not be read-only. And this is saying that it needs, okay, alright, so let me, let me backtrack and card so mistakes. So when we set the soap in the register of the i units offered, this should not be Gets it, this should just be get. So let's take off this set, right? These should not be get sets. I created all of these images areas then from no. All right, so that should just be a get me anywhere, just getting that object. And then the public one node is going to retrieve that object and put it there. So that's pretty much what our unit of work look like. Now when we come back, we'll see how you refactor our makes controller to take advantage of the unit of work and then run it through some tests. And then we can implemented across the board for every single domain object that we're going to have in our program. 20. Refactor Existing Controllers to use Unit of Work.: Alright, welcome back. Now that we have our units of work setup, what we want to do is start refactoring our controllers. But before we can let our controllers interrupt to the unit of work, we have to let the Bootstrap or know that this is an injectable service type into our application and anything else that may want to have it dread. So what we need to do is go to startup. And then right on the knees, the ad identity server, JWT, I'm going to add a line, added transient i units off work units 04. We can go ahead and include any missing references accordingly. And what happens is that we're doing, I'd trends Indianola, I'd transient, add scoped and add Singletons. Singleton means that it is going to be one incense for the entire runtime offer your application. Sculpt means that it's going to create, well, it's going to be one instance for the lifetime of a certain set of actions. And then I'd transient means that every action is going to spin up its own verge on pretty much. So we want to make sure that the units of work is not, you know, it's, it's being unique each time. And well, we already have the garbage collection, so as soon as it's no longer needed, it will dispose off itself anyway. So that is whole or units or four, it gets injected or gets prepared for injection. So a null anywhere that we wanted the same, you could inject application DB contexts or any other service. I can know inject my i units, so 4k, so I'm going to Snyder factoring right here in the mix controller where I'm going to say i units of work. So I no longer want to directly interact with my context. I want to start using the i unit of work as that intermediary, right? It's go ahead and include any missing references. And then I'm going to call this unit of work. And so the injection null will be not obligation DB context bullets. You get off work, right? And then the initialization pretty much follows the same pattern as with anything else that we have been doing that involved injection. So note that we have the i unit TO for replacing RDB contexts. We have a slew of errors that we need to work through. And let's see exactly what happens. So here it said return an enumerable of Mick and it went to the database, the table and then converted that. So that would've been lead II queryable into a list. So what I'll do here is say i units, so four mix. And then I can see, Give me the gets. All right. There we go. No, I'm getting an error here and it is partially due to the return type versus what I'm actually returning. So I'm actually going to do a bit more than those refactor that needs a base color. And I'm actually going to build all this controller the way I feel more comfortable with my controller looking. So I wanted to change this to be just a task of type. Action results on when to take off this strong datatype. So task off type actual results. And then it's expecting some form of HTTP. Response to be returned, someone to expand this a bit. Var mix is equal to, and then we made that phone call. And then I can see return. And I wanted to okay. So remember that when we were looking at the return types, who would've seen the old key or the content and so on. So all k's a 200 response that allows me to put in the data that it should return if everything is all right and that's all you have it, right? So yes, more lines of code are away. The one more line of code. But to me this is far more readable and it's easier for me to maintain. And based on what we've implemented, you see everything works anyway. So there's nothing wrong with changing the generated code as long as you understand why you're changing and once you understand what your change in the near or on the right track. So let us do a similar operation for the Get with the parameter. So task I axon results. I'm removing the strong data type. And then what we'll do here is see way too tough work dot mix. So I'll just replace all of that. But then this time it's a get. And then instead of passing in the ID, once again, we could have had I get four, get by ID. We could have had I get by something else, right? So the flexibility of the expression is that we can put in the lambda experts on here and say q dot. And then I can see ID is equivalent to ID. That's my lambda expression. So that condition is going to get executed like we saw, like we implemented in the generic repository. And it's going to go ahead and return that one mic. And then here I can return, okay, with the mic as the data being returned. Once again, if you're used to the wrist, design risk principles, rest API, development, then all of this will make sense to you. If not, then no problem, that's why we're here. So that's why does two endpoints Don't just a few to go. So for our update, the modifications I'm going to make will be on the score Unit 04 dot, makes dots. Alright, so because of the register, we can access and mix directly for about 2 that told earlier. Well then we can say update and then we just pass in the entity which is off mic, right? So me, which is the MIC coming in through the parameter here, and we send it all. So this line of code is going to be taken care of in the repository. So nobody needs to look at our controller and know the deep dark secrets of what's really happening. Alright, that's that abstraction. And then for an operation like this, when we modified the data, we need to call our Save Changes. So I'm going to take this old and I'm going to see you when it's off four dot save. All right. And then that's it. So let's move on. So you see, the refactoring is really not that much, but to me it's, there's not a lot of databases heavy activity happening in our controller. We want to keep them light and clear as possible. So for the post, we want unit off work to mix dot and then we'll see insert, right? And what we're inserting Is the mic. Alright. That's asynchronous. Oh, and it's asynchronous and I forget to put on the await, you see a green squiggly line. So and then there are all asynchronous which is ready to answer me going back and putting a sink. And then from here I'm going to SI units are four dot save. And then I can remove that line and everything else will flow accordingly. For the SAC, once again, the button is there. It does work, but you may not need it. So I'm not telling you that you must develop with it, but I'm just guiding you as the whole. You can go about implementing it. So what do we want to delete? Remember that delete, delete only needed the ID, right? So what we can do here is you get off work, dot, mix, dot, delete, pass in the ID null, where actually kind of bypassing some of the more essential ticks that we see here. Because what it's doing is finding if the record exists, if it doesn't, then it's going to return, not phoned. And then of course they wanted to save changes after that. Right? So just reduced all of these into more like two lines of code. But then, like I said, this check is kind of essential. So we probably can do that check where we say mic. So we're going to get the mic. And then remember we already did this somewhere up here where we did this get. So we can do that same get ready. We just say get me the mic. If the mic is equivalent to null, then return NOT_FOUND auto as we carry on with that. And then we can just remove anything else that is there. And it was C. And then we have this method that says Make exists soul. You could implement in the unit of work C. When you pass into ID, you check if any. But we already have this method that's going to check if anything is there someone to use this and replace this is exists somewhere to say var me eq is equal to that, um, and then it should return a Boolean. So I'm going to say return me is equivalent to null. All right? Our soul here, this is asynchronous, method is not. So what I can do is make this an async task that returns a boolean C, u, that I know everybody's happy. And then of course the method call has to have the outweight up here. So that's all, everything kind of flows, right? So that's just the reflective for the mics. If you had generated, they'll they'll controllers and he can go ahead and do that. Otherwise we're still going to do it together anyway. But let us take this refactored control for a spin. Note that we're using are units of work. And just verify that it works from postman. Alright, so I'm going to start off with a get request. So if I send then we get all the vehicles or sorry, all the models or the mix or other in the system. So you see, it does work, it still works. It makes our quote ended to cleaner and segmentation is kind of in place. If we wanted to create, it's the same principle. I can go to school here and see Send, and then it creates a new dummy car. The kids will work the same way. Everything will state. So let's see what happens when I delete an ID that's not there, cause removal. We already deleted the mix with the ID for lets us see what happens. See 404 Not phone. If I move it up to five, which is the dummy guy that we just created. It's null contents, so everything still works. No one thing I wanted to point out is that when we're creating our, you know, anything, we really don't expect to get this stuff from all our clients, alright, so created by big created all of that shouldn't be prevented by client and postman should be Really emulating what a client would do. So in this situation, if I wanted to create that DO make car, anything though MCAR id seeks, and then these fields should really be auto filled, right? So you see here null, I don't know who created. It's I don't know when it was created or updated or anything. I don't know anything like that. So we we really should be implementing that. No, I had pointed out that what we would have to do to facilitate something like that would be that on the put, which is the update, I would have to see me dot it, create our digital data is equal to this. We don't want to do that. Once again, we don't want to have to do that across ten controllers are every time we get to our controller, we have to do that against the entity manually. So what we're going to do is implement in our safe operation the ability to get the HTTP contexts and modify the objects before they go off to be C. Alright, so let's focus on adding the deeds. So the scenario is that when I create something that D created and the data updated should be the same. However, when I did something on that date, updated and updated by should change. Alright, so what we want to do is this safe operation, we're going to save var. I'm going to call it entries is equal to get me the context dot change truckers. Because remember I said that once that data is coming in, or I mean, once you are creating something, once we are orbiting something, it's not tracking the object. Once we have retrieved it, because we said as North tracking, there's no tracking. So chance structure is really just going to see okay. Anything that's I am trucking, get me all the entries and that's a method. And then I'm gonna just say it dot to We're, so I'm going to run a lambda expression on, on the database or query to see where the Lambda expression Q dot state is equivalent to NTT State, which is really an enum. So I don't like having all that fully, full qualification. There's entities theatre and include the missing library where entities, states dot modified. Or I'll go to the next line for that are the q dot state. So the state that's it isn't. So remember when we did the update, which is the state, right tool entity state DOT modified. So I can see dot modified, our entity state is dot dead. So that means it's about to be created art. It was just added tool that tracking, or at least as far as it's concerned, it tells little id for too much. Then I'm going to loop through all of them. So I wanted to say for each entry in whatever came back in entries. Because the reality is that when we call c, If we might have touched many different things, right, we have the whole update_many who could have modified on make and model. And we're trying to make one save operation and we don't know. So that's why we're just getting from all of the entries. That's our boat to be saved to get me all the results are modified and all of those that are added. And then for each of them, I want to change their modified it and modify it by, right, we're not ready for the modified by focusing on the data retinal. So what I would have to do is see entry dots and then say entity. But then the problem is that entities very generic. It doesn't know what feels it has, its, it doesn't know, right? So one of the advantages with those using that BCE domain object is that we can always cost and entity into that base domain object, which gives us those audit fees that we know what every single field, every single domain objects are allowed. So I can say b is domain model here. And then I can wrap all of this in one big parentheses, so it will see it as one big object of type baseline model. Then I can see dot updated, data updated. Let's focus on the funnel is time, datetime dot naught C. And then I'm going to see if the state, so in tree. If this state is equivalent added, then it tends to get special treatment because in addition to getting the data time, it also needs to get the created the threat. So I'm going to copy that and I'm just going to change this to created, date, date created. Alright, so basically I'm saying that anytime the save operation is being done gets anything that was modified or added. And then for each of them that you got the data to know because clearly it's being updated and any of you was added, go ahead and fill it in So if it's being updated, I don't need to update the added part. And then after all of that, we will go ahead and save our changes regardless. All right, it doesn't get any more, much more complicated than that for that. So once again, this scanner system at that time of having to remember that on each control, at every operation, I'm trying to track all of this because just automates it right here. So let's take this a step further and look at how we track the user. Because I'm logged in as a user and I'm doing my daily operations, I really probably don't know that you are tracking me, so I shouldn't have to type in my username alongside any work I'm doing when I click Submit, you should be tracking that. I am the one who click Submit and our audit fields do that. But then how do we get the data from the person using the blazer up to the database? Well, we are going to allow for the inclusion of what we call an HDTP context. Alright, so you know, I save operational, we're putting in this parameter HDTP context, which is coming over from our controller. Alright? Because we know that that's what we call safe from. Everytime we call saved, that's where we're finding it from. So of course, if I update it here, I'm going to have to update it in the unit of work. So C-F is expected to have parameter of type HTTP contexts. So soon go back and update the controllers accordingly. So when we get the HTTP contexts that gives us access. So maybe the user name, uncertain things, a boat, a controller, so any requests coming in. So I can say var user is equal to. And then I can see HTTP context dot user. We've got that dot identity, dot name. So that gives me the username. Alright, so I wanted to truck which user need lot. Well, here it is. I know how the username. All right, so I can also see that anytime something is about to be updated, that the updated by is user, right? And then the createdBy is user. And then from our controller, I'm going to have to make sure that anytime I save, I pass in this dot HTTP context. And then I have to say, well, yeah, this dot HTTP context. So that's actually sufficient. I think I don't even need the keyword that's actually sufficient. There we go. So I just Boston the HTTP contexts, so it's automatically going to truck. Okay, this user was the one making the request because the HTTP contexts, it's trucking everything about anything happening, happening, the connection that's being used, the user, they request the responsive writhing is in this object, so it was possible without object. And then the units are fork CM operation is just going to be one big war cars while it's putting things into the database and putting it on all the audits. So this is a nice way to get audit logging in your application. Oh, maybe depending on the developers to make sure they put it in or depending on yourself to remember that puts it in all the time. So let's test that. Let's see what Postman is going to be seen as. We try to submit data to the database. So I'm going to put a breakpoint here in our safe operation and then let us test creating another dummy car. So I'm going to see Send. And then our save operation jumps into action. So when I look at the name, let's see what name is there. Let me just do F 11 and then user, while the user is null because nobody's logged in. Alright, so that's why user is still novel, but that's fine. So when I look at the entries, I mean just do F 11. So when we look at the entries, we're going to be able to see that we have this one entry being added, C, that's a state being added. Alright, you can try and break down, but once again, everything at this level, it is very generic, so it's not going to show anything specific or to specific, which is why we had to do all of this typecasting to get to tin. But I'm just going to press F5. Let's continue. And then when I look results, you see dummy car and data. We know c, our D, it's coming back. So I didn't provide any bits, but the dates are coming back because they were put in automatically by our code and updated by, and created by our null. Because as far as it's gone, senders and all user associated with the request, the request just skimming. Alright, so that is one of the ways that we automate our logging and audit logging, sorry, with the unit of work patterns. So at this juncture, we have done some very critical things. We have one implemented or units of work beads. I've shown you how to do it for one in one table, but we already established that this i unit of work section is really like a register. So whatever we just did for the one, we can replicate it across the others. For the unit of work, you have to do the same thing here for vehicles, for models wherever, although one. And we don't need to go back to the startup because we already dealt with our injection there. So that's fine. We don't even have to do anything more there. And pretty much if you scuffled it other controllers, then you have to refactor them. Otherwise, if you haven't scuffled at others, then I would suggest that when you do app.controller, you create an API controller just with the read, write actions so that we probably do and tough to do as much work what you do with the Entity Framework and he just made a few changes then that's no problem also. So I'm going to challenge you to do that in the next video, we're going to come back and I'm just going to compare notes with you just to make sure they'll show you what I did. And so you can just look at what I added to and make sure that you're on the right path. 21. Refactor Existing Controllers to use Unit of Work - Compare Notes: Hey guys, welcome back. So I left you guys with quite a bit of a task last time, but we're here to just compare notes and I'm just going to point out certain things that I'm sure you've gotten if you didn't, then no problem. I will point them out for you and you can go ahead and complete the activity. So what I had shown you was one setting up the units are for, and we only did it within the context of the mix table. So initially, we would have only had 11 thing, quote unquote registered in these units of work interface. So we went ahead and registered all the others for model vehicle, color book, King, costumer, and any other domain object. Now you may have the need to include, you can go ahead and just continue this list. In addition to that in the concrete class, who would have to make our private corresponding fields for those. So make, we add mic, Boa to meet for models, colors, bookings, et cetera. And then of course we had to kind of do the initialization of the public objects, right? So kind of a space that's unrestrained to take on so you can see them all more easily, right? So the same way we did make, literally I just copied and pasted and then just changed the mic to model and the corresponding text. That's really all that needed to be done and is strongly typed. So if you made a mistake, you'd see a red line. So that is what we did for the concrete unit of work implementation. Now, after doing all of that, I went ahead and scaffolded out all of the other controllers. So you see on the controls you see bookings, colors, costumers, models, and vehicles we created mix together. And to be honest, all I did was copy most of the code from the mix controller and then go over to models and then paste it and then ended up control F, where I looked for anything in this current document that said Mick and I changed it to C model or well, Ken Pienta and model. Alright, and that's all I did. And then replace because what happens is that we have the unit of work already. If it said get me x, then after doing this, replacing would know, say get models, if you'd said makes here is now going to see models. Everything just change those AS even the variables. Now if capital m is which is offered little consequences of the grand scheme of things. So I'm just showing you that, you know, if you labored through, they didn't do the copy and based and so on, that's fine. Maybe you wanted to do it to get their experience and that's good. No problem. We'll start it there. I'm just sharing with you Hawaii kind of expedited procedure. So if it is I you're not finished with the operation and you find it tedious, then that's one hint. To help you carry that on more quickly. For the root, just remember that we're not using API slash. Sonya scuffled them, you'd get api slash controller. So I went through and made sure that I had to call the API slash Alltop, all of them. So they also just say controller. Alright? And that's pretty much it for our rest API. There's not much that we need to do are much more that we need to do here. At this point, it is well prepped and ready to serve our Web Assembly client application. And so in the next video, we'll just hit our checkpoint where we go ahead and check in our code. 22. Review and Add Changes to GitHub: Are you guys all? We've come to the end of this section where we spend our time prepping our rest API to serve our client application. What we did was to make sure that we tested or endpoints. We created an endpoints that spoke directly to the database and we saw it work. But then we had a discussion around why it's good to implement other patterns on top of what is scaffolded for us out of the box. And that reason, the reason for that really was for maintainability and certain types of automation that we can put in going forward. So the weapon of choice was the unit of work on top of the generic Repository pattern, where we have the generic repository being implemented to be, as the word suggests, that generic. So we, we are not strongly typing it to any one class, but any class type that's his fasting, we have these operations that can be carried out accordingly. And then on top of that we have the unit of work where we registered the different implementations are the strong and the typed implementations of that generic repository. And that allows us to make calls to them at will. We also looked at customizing onreceive method, where we can go ahead and inject our HTTP contexts, allowing us to get the user who is carrying out an operation. And then we methodically go through all of the records, a boat to be sieved, and check which one is modified, which one is being added, and set those audit values accordingly all before the beak save. After we looked at all of that, we made sure to register it in our startup file, so that allows it to be injected into any other parts of the application. And in particular, we're looking at our controllers where we refactored the one that we scuffled it to then use the unit of work as opposed to talking directly to the application DB context. Following this example, we scaffolded are created controllers for every other data access point that we might have going forward. That is the standard that we will be using should we need to extend this application. So at this point, we're just going to go ahead and check in all our changes so I can bring up get changes some not seeing it here. What I'll do is just go to View and they're good changes. So from here I write my missile and it's a straightforward message editors, API endpoints and the unit of work pattern. And then go ahead and commit all and sync. And at that point we have our updated bits of code. So see you in the next lesson. 23. Section Overview - Working with Blazor and Data: Hey guys, Welcome back. I just wanted to give you a quick overview of what we'll be doing in this section. So I have open the fetch data components that would have come as a part of the some application from creation of this blazer projects. So I just wanted to point out a few things and give us synopsis of what we'll be covering in this entire section where we'll be talking about using blazer to communicate with our API and manipulate the data accordingly. So this fetch data arrays or component one, represents a component similar to what we will be creating. We already kinda went through how we create a component or some seepage and our shared and all these things. So we, we have a basic idea of whole component creation goals. But what we probably didn't focus on was what was happening inside of Fichte data where one we are authorizing. So you saw that when we try to navigate to fetch data, we have to login in order to proceed. That's one. Well then you notice that we're also injecting this new bit of code called HTTP client. Know this HTTP client just represents a library. And the way you would have seen the configurations for this HTTP client over here in our program.cs. And it is configured to look at the server project, the server API as its address. Alright, so in other words, it's going to be looking over at the API automatically. So HTTP client is configured to look at the API given to us through the server project. And then this object allows us to take advantage of some of the functions that allow us to interact with the rest API. So I'm just going to skip down to the latter part of the code where what it's doing is it is initializing, you know, a list of data that to take spikes. And then when it is initialized, it's going to try to retrieve through our HTTP client object. And then it has built-in functions for all of the verbs that we went through in the API. They get the post, The put, all of those we'd be looking at. And then it was C realize that JSON data that we saw from postman from our tests. You will kinda serialize whatever data it gets back into the matching class. So far, all the field names that much it will actually fill the, this class and it will just retrieve all of that in the form of these objects and store them in forecasts, which we see just a collection of the data coming back from the API call. Now what is over here in the string would be the address that it will cause a weather forecast here corresponds with the weather forecast controller in the API. So our HTTP grant means that GET requests and we see, we see our verb, HTTP GET, which is really just returning some random stuff in the form of an array. All right, so that is really a synopsis of whole. We will actually let the blazer components talk to the rest API. You can see it's really not that difficult. So when we come back, we'll start off by creating a list component where we can list out all the data in the database on a blazer pH and displayed to the data. And then we look at all the other crud operations. 24. Blazor Display Data - List: Hey guys, welcome back. So following our quick overview of this section, we're going to jump right into it and we're going to look at how we can create a components that will list the data from our database. So it's always a good idea to kind of organize your files in folders as we've been doing up onto the nose. So I'm going to start off with the page is parts of the car and management dot client project. And I'm going to create a folder that I'm going to call that start with mics. So of course, you'd want to have the ability to see all of the files per table in your database with some exceptions, right? But the point is that we have bookings, we have colors, we have customers of mix, we have models, we have vehicles. So that means that for all the crud operations that we're going to be doing, we will want to do them across each of these datatypes. So I would want to kind of clump all the related components per table or per set of operations into one folder. So if I have a mix folder, then I'm going to have a model's folder and so on. So I'm just going to go ahead and create all the folder. All right, so that's the kind of organization that I am going to be maintaining. Know for this section, I'm going to do two examples. We're going to do an example with the mix, which is simply enough because you know, it really only has a few fields anyway. And then we're going to do one with maybe something more complicated like vehicles, which has related entities, right? So I went to do those two. And then of course, you know, our pattern is that I show you the concept and then you try it on your own, and then we'll come back and compare notes. So let's get right into it. So in this lesson, once again, we're looking at hallway are going to retrieve data and display in a list or in a table form for our tabular form for our users. So we start off by creating our new components. So I'm starting with mix, I'm going to create a new razor component. Then I'm going to call this components what I think the pH should be called. So I wanted to call it index. All right. It is always, actually, I'm going to say it's recommendable to think it's actually required. But I am, if it's not required, the lambdas recommending that we always name or components with capital letters. All right, So index like epithelia, I go ahead and hit OK. And now we have our component. We have seen components before. We already looked at it when we did our sample component earlier on. So this is nothing new to us. However, we're going to try and make sure that our root is there someone to say at sign page open and close quotation mark? And this one, I'm just going to see slash mix, which means anybody who browses and says slash mix should be able to hit this component. And all the thing that I'm going to make sure to do is to inject our HTTP client. So just going back to fetch data, you see that that to inject HTTP client into the hole, into the, into the component so that they could talk to the API. So we definitely need that. We can also look to inject some of these, but that are putting these using statements like we are going to definitely need access to the sheared. And they'll mean sexual and what don't we just show you how to do that in a cleaner way, more global way. So we don't have to do this every time we need it in every component. So I'm going to start off with injecting. And I'm calling my an underscore clients, That's my naming convention, but, you know, you can name it whatever you feel more comfortable with naming it. I wanted to change this h3 title to be of class card title. And I'm going to change the text to say Make list art or, you know, probably list of mix. Our car makes something something that the user I'm sorry, I'm just getting invited over those tiny things. And I mean, we can work on certain design elements. You might have all the ideas in mind, but I'm just putting in these elements nice that the horizontal rule and then a break point, our break tag, sorry, to separate the title at the top from the rest of the content. Know what I'm going to focus on is what we're putting in the code. So I'm going to start off in this court section. What we need to do is to upfront see that we have a pH model on what data type it is. So I'm going to say private. And since I'm dealing with mics and I'm neither a list of mix, I'm going to initialize list of type mic, right? Notice mic not mix cosmic is the datatype of the table that we're dealing with, right? So meek. And then I'm just going to call the object model. You could call it makes, you could call it whatever I like to call it model because that's the model for the Peach. Now I'll make is giving an arrow because once again, I need to sit in the using statements so it knows where it can reference this from. So instead of doing it the way that I just pointed out, Fitch data is doing it where it's doing the using statement directly inside of the component. What I'm going to do is go down to imports. And then from here I can set some kind of global using statements, right? So I can see under here using current management docked, sheared dot domain. And then by doing that, any component that requires anything from domain will know that while it's already in the import. So I don't have to come here and see it again. So I did it one time. I'm only doing it on this component, but in the future you'll notice you don't have to do that part again. All right, so now that we have our model defined, what we want to do is flesh out our protected is sink override, override task. And this task That's a multiple but don't worry, will do is called uninitialized async. So that is a built-in method that every component has uninitialized async. What do you want me to do when I am initialized? That's pretty much it. Notice it's an override. So the base class upon which every component is based, right there it is. Component b is. Sorry, task component based on initialized async. So we're overriding the default one and we're going to say what we want to do when this component is initialized. What I wanted to do, I want to get the data storage and the models. So I'm going to say a model is equal to and then I can, I'll wait, my client doing a call. So the client, the HTTP client has method's built-in. So I can say get from JSON a sink. All right, it's, it's automatically going to go and and de-serialize whatever it's getting. So what is it getting? Go out to specify what kind of value I expect to get. So I wanted to say, well, I expect to get a list of type mic. All right, so then that's going to say, okay, you want to list off the mic, where do you want it from soft to put in the address of the place that I expected from. And they address would be the end point. So remember that when we looked at the program.cs, it's already settled the HTTP client to look at the base address of our application, right? Base address, meaning what is the address? So notice that the server and the client, they both share the same address just in case you've forgotten lawn settings.js on local host for 4385. And if we do the same thing for the server, it's the same address. So the base address, it knows where the API is. However, we need to tell it which endpoint offset API. And then based on our naming here, which I do believe is going to cause a conflict. So we're probably going to have to change yourself, but let's just start see the error and didn't fix it afterwards. But we did say that endpoint should be the names of the controllers, which in this case means makes is where I want to go. Where are they tested API and looked at all those endpoints though. So I'm going to see, go to the endpoint makes. So this, this component, once it's initialized, is going to make this API call to that address and get the list. And we know that it's going back in JSON. So this function or this method is going to automatically reconstruct the JSON data into a list of me, strongly type, strongly typed, sorry, so that we can use it and manipulate it all we wish. All right, so this pretty much takes care of that API, will get me the list of makes in the database and stored them here inside of this object called model. So no, how do you display all of this, right? I'm going to see firstly, if outside-in model are, sorry, I don't need that saved my butt. So if model is equivalent to null, then I want to display something seeing loading or it's going to put in a div. And I'm going to give it that class goes, remember we're using Bootstrap, so alert and alert me to be in full. Alert in full. I think I passed it. There we go. And then I'm going to say loading makes loading mix. That's blue, whatever loading message you want. So the point is that we're always going to start off empty. This is going to be null because this means it's null. But then once this is completed, then we want to display a table. So this is going to be. Displayed while all of this is going on, however long it takes to go to the API, this will be displayed. Then the cool thing about blazers that wants the data changes. It sends a message back to the UI to say, Hey, you know what the data changed. So the mere thought, that's again those, you know, it's monitoring when this data changes, I can see if it's null, do that. And then when it changes, it will always reevaluate is it's the normal. No, it's not. Okay, what should I do here? Right? So it's almost like a while loop without the loop, it's so cool. All right, so what we're going to do that point is C, Want a table maybe. And then I'm using Bootstrap classes for my table. So I'm going to set this to have table and table that's responsive. And if you're not so familiar with Bootstrap, we can look at the other ones you probably want to include, but I wanted to stick the table responsive and maybe SM Well, no, let me just give you that table and dealer responsive. And then define hold this table should look so we have our T head, which has a TR, which then has the th is I'm going to have th for name as in MC, name, just looking backup mic, make really or layer's name and ID based on the based domain model and created by a Slovenian number of details you want to include getting through them right now I just need the name and I'm going to have another column called auctions, which is going to host, you know, edit buttons, delete bonds, et cetera. Then after defining the head, I'm going to put on the TI body. And then in the team body is where we do the fun part where we have to loop through our data, coming back, you know, model which we know is of type, list off mix, right? So I'm going to say for each item in model, I want a new role, TR, with the first cell being playing home to item.name. Alright, so you see I'm giving up all objects because mobile is of type, make. Each item represents the maker it. And then I wanted to have another T d, sorry, in the same rule, which is then going to store all of my buttons. Now this is what I want my buttons to look like. I want anchor tags. I have two anchor tags on, I have a button so you can pause, take a look at what these code is, and then continue. All right, so my first anchor tag has the HRF to go to mix slash view, right? So we're going to be setting up all of those, but this one would mean that I want to look at the details of this record. So I create the view button and I'm passing into item ID. This one means that I want to edit maybe. So I'm passing in the ID. This one is the delete, but notice it's not an anchor tag, it's a button. They're all using the same Bootstrap classes. Shore are just variations based on operation. But then the button has an onclick event. So if you've ever worked with wind farms or even web forums, you'd be used to click events. So this is like a little click event where it's going to see that I want to call this function called delete and PaaS in the make dot ID. All right, Sorry, I hit him. Alright. Alright, I had mic. The point is that probably you want to do this because, you know, when you're seeing model, when I'm seeing mod 2, they had 10 or 12 this. So let's just make it a bit more reader-friendly, right? So this is a list of mix. All the mics come in and do that. And then anywhere I said mod lambda is going to see me x instead. All right, and then instead of seeing item because you know, the code when it's big lead that can be harder to read for somebody else looking on. So let's just make it as reader-friendly as possible. So changing all the vague or for instance, the item on model to say something more like me. Alright, so make dot ID and then we have our delete method reference here, but there's no delete method to call. So what I want is that when the person clicks delete, when the user clicks delete, we just give them a quick prompt. Are you sure you want to delete and then if they say yes, then we go ahead and didn't eat, right? So I need a methadone here that I'm going to define as an async task. And it's going to be delete or, and I'm going to make it take a parameter int id. All right, now what do we want this delete method say, so that goes away because I'm calling a method. It just didn't see it yet. Know it's there. It's fine with that. Right. And that made it a sink. You see why in a minute. And notice I don't need an access modifier because it could be private. It doesn't really make sense. You make it public. But in absence of seeing private, it implies that this is private. So you didn't need that part. So I wanted to look up the mic. I'm going to say var MC is equal to the and I already have the least off mix. So here's a cool thing. I already know the mix. There are the hearing, the component. I don't have to go and make a model API call it to retrieve the myth that needs to be deleted. So I can just look into the list that's already have and say give me the first one they want to sit for a store, for a store defaults. I just do first and I'll see my lambda expression. Let's try that again. First, where Q dot ID is equivalent to the mic ID that was just busting through the parameter which came from our button click event against that particular record in this entire table. So you see everything is just contradicted beautifully. So then I'm going to say if I want to get a confirmation from the user, so let's just do it firstly, without a confirmation, Let's look at a code without a confirmation. So after doing this, I can say await a client call to delete a sink. He said that. So for every verb, the HTTP client has a method. Alright? And then I'm going to be calling my mix. So I want to call mix slash goes, remember that's the name of the endpoint. Right? Makes slash and makes for the delete took a parameter. So let's just go back and look. So we took a parameter for our delete, so it has to pass in mix slash Fiverr. So I'm going to say makes slash and then put in the Meek ID that was passed in. And then Going to recall the initialized async method. And because we're using our weights, That's why we made this method Async art. So basically we delete and then it's going to refresh the page. Now I did say I wanted to prompt the user because you don't want the user to delete. And I just refreshed and they're like, Well, what did I click? So all we're going to do is probably put in a little prompt. And you know, like in JavaScript you can always see like alert, something like that. We're going to do that. We're going to put in an alert or JavaScript prompt. In order to interrupt with JavaScript through blazer, we have to, we have to inject another library called IGS runtime or JS interrupt. That's the technology or the library behind this JS Runtime. So with this object, we can know interact with some JavaScript code in using C-sharp. It is just, I got a nice hybrid way to not tough the bones are prone to many languages to accomplish using all of them, right? So I'm going to say if, and we're going to often, I'll wait, JS dot invoke a sink, right? And I expect a Boolean, so I'm going to tell it you're expecting a Boolean after you do this invocation. And inside of this method does methods. So after the angle brackets with bool, we just open and close parentheses. I have the first parameter, which is seeing what kind of method from JavaScript is it's supposed to call. Pretty much what parameters are needed for SCID methods. So confirm, that's the method that were calling. And then I'm passing in the text, do you want to delete and, um, those super or interpolating mic dot name in there. All right. So this is an if statement. So if yes or no, so confirm is going to be yes or no, so it's waiting on the response and it's storing it there. So all that oxygen, so that one hybrid, each statement, just writing it in one line. If you wanted to separate it, you could say var decision or var confirm is equal to, let me just put that in there from NOW is equal to this gene is involved so that you know, you can kinda pseudo code a bit more, right? And then if confirm, then we call, alright, so that's pretty much what not. And that's a simple, very simple example of all the js interrupt runs. Later on we'll look at more advanced and probably more beautiful ways of getting this done. But for null, we've done quite a bit. Let us go and test. I think we already had put in some mix in our database, if I'm not mistaken, right, so we should have at least a few mix to look at. So let's see how this works. So I've just loaded it up and I realize I don't have any immediate way to get there. So let's buck chuck up bit and make sure that we update our nav bar. Skip that step. So what I'm going to do is get rid of this sample page and even the fetch data were really don't need those. What I wanted to start by changing the fetch data, I'm going to say Meeks, alright? And H ref here would be mix with a slash, right? So that's saying Go into the mix folder slash and then we're already told the index that you are at that address, pretty much right? So this just restart. All right, So no way of our menu item if we go there, it's going to start loading what it's going to give an error. This error really is because we're trying to make that API call with the proper security clearance as well as Luke. So I did allude to the fact that we might need to change or address for the API. So this is actually seeing slash mix. What do we told the component that is also a snatch me x. So when to write my initial or wrong where I would've suggested that we just go by the controller. Because what happens is that if we go back to the controller and then we name our folders the same names, then the upward kinda get confused. Am I going to mix on the server and the BIA or am I going to it in a client? So for corrective measures and that's just re, do are those Roebuck, our standard for the API, api slash controller, right? And I want to do this in a simple enough way where I'm just going to do a find and replace. So I'm just going to say find square bracket controller square brackets and replace it with api slash. Square bracket. And I'm looking in the current project and I'm just going to replace one at a time to make sure that I don't so I don't need to replace that one. But I do need to replace this. Skip or so others. Yeah, anything that needs replacing, I'll just do that. And we should be good to go after these messages. All right, so I'm just pointing out a potential classroom, not potential at a crush that we encountered. And we can leave the weather one because we don't really need it anyway, and that's it. So another thing, another change of them went off to me it noise to the API address that's being called because I only said mics. So I need to see api slash up here and api slash at this point. So let us do that again. No, another point of information before we continue. While we did not put any authorize on our view on our components, Sorry, we didn't put any author as on the API either, right? But we actually took it off. The thing though is that the configuration of the HTTP client in the client application and program.cs does say that it needs authorizations, so that means it will always try to symbol will authorization. And it's just configured to know that it should be an authorized call, meaning whoever is calling should be signed in. So while we didn't put the protection on the page, it might not work because it's going to try and do an authorized call. All right, There we go. So while it's not showing us the API stuff, we'll fix that, but we still have a problem. So it's a simple enough problem to get our own because we already have some users that we created. So I kinda slow. And then having logged in, I'm going to try again and there we go. So quickly made that call. Well, I mean, everything is sitting on a machine and soul it the fund that's emitted on API call and came back is transparent to the user. So here we are looking at all of our cards, are, sorry, our Meeks in the database, right? And then if I wanted to delete, since that's the only other functionality of system so far. Again, try that. I get the confirmation. Do you want to delete dummy car? I click Okay, and then look at that. So it's like everything is happening real-time. No real visible reloading or anything like that. I can go ahead and delete the other dummy car and we have our data. So any cosmetic changes you want to make at this point you can make and so on. But this is the basic, those are the basic steps towards getting the list and displaying it in a tabular form. 25. Blazor Display Data - List - Compare Notes: Hey guys, welcome back. So in our previous lesson, we walked through setting up UI such that we can retrieve data from the API and display it to our users? No, I just wanted to walk you through some of the minute changes that I made to the mic speech. And then I'll walk you through how we transferred the knowledge of what we just did from the mix component as a pH component. I'm using them interchangeably at this point. But all of the techniques and we'll want to record who put in place to make the mix UI work. I wanted to be walking you through how I hope we transfer that knowledge or can transfer that knowledge to the other parts of our application. Now you just miss me critiquing mix and then you notice that it went straight over to the login page. Why did it do that? So the first thing I did was to add an authorized tog or Flagler attribute to the top of our mix page, right. So I'm just bringing it up. So I said attributes authorized. So remember that we pointed out that each time the API call is made, it needs to have certain kind of tool can which indicates that it is unauthorized user who is making this call. So I just, by putting this at the top, this authorized attributes on the top of the UI. It is sending the UI that you have to be authorized in order to access this. And this is what happened in the Fetched Dates are component, which is why we have to login before we can proceed to get to the finish date. So I just put that in to make sure that we avoid an institution of anybody trend to load this page and getting that error when all they really need to do is login. So we're forcing them to login with this attribute. And although change that I made here was to haul, we formed the endpoints. So I had to put api slash mix and then don't hesitate to say api slash mix again, slash MC ID. And pretty much that's a pattern in time. We want an address, we have to say api slash the address. So what I did was I created an endpoints file which I put in a folder called static. So I created a new folder in the client project called it static. And then I have C, C-Sharp class called endpoints. So this class is a static class which has just a bunch of static strings read into that could've made this private, but that's okay. But I set the prefix, which is API, which I mean it's applicable for all of them. And if you change it from API, it's something else, then you just need to change a prefix one time. But then for each potential endpoint, I created another static string so you can pause, do all of that once again, creates a folder. Go ahead and create, sorry, it creates a folder called static create the file called endpoints are C-Sharp class rather. And then in that class, we can just put in this bit of code. And then of course, after doing all of that, you want to go to the imports and let your client application know about that namespace so we can use the cross all the components comfortably. So that is, those are two changes that I made to the mix. Now in terms of transferring the knowledge or the techniques used in mix, and I'll just login so you can see. If you look at models and the lookout colors, they're pretty much the same thing as mics. They only had one property which is name, right? So I just did the same thing for models, that the same thing for colors, right? So we had the folder is created from before. All I did was create a new index. And pretty much you make sure that the path, this is colors and all would make sure to path we need the same libraries, the same authorize that we are using the same H3 card title colors. Really and truly this is identical code, but for the fact that we're using the different endpoint. And probably verbiage is different here and there. Once again, it's your application. You can tweak ITO, you need to. I'm just showing you that the same techniques that were used for the mix, we can use them for every other one. All right. So in all fairness, all I did was copy from mix, paste that index file inside of colors and inside of models. And then did a Control F and found every mic and replaced it with the word color. And I did that for both uppercase and lowercase just to make the editing much easier. And then any errors along the way, we just clean them up. That was it really no, I'm more advanced situation would come in the form of vehicles. So customers is not very different. I mean, you know that we didn't have much for customers. I mean, we could have put in a bit more data maybe for Dan just tucks ID contact on email address, maybe firstName, lastname. But that's fine. We can do that later if the need arises. But once again, it was just as easy as it was for the pre-built Swan, our previous ones, except you have to be mindful of the columns that you're putting in. And the father, you need those additional columns and everything else is pretty much the same. And I just had a minor adjustment. So of course you'll want to be very careful and meticulous when doing you're copying and pasting because see, I got sloppy with mine. But it's good for you to see what can go wrong either way. So I'm just making sure that anything that said MIX No says customers and thinking that said meek and also its customer, right? And basically everything else is in tucked and in place. So we can move ahead. 1 though with the authorize attribute, it will tell you that you need a library. Forgot to mention that. And you can also take care of that requirement by adding these two lines to your imports. So no matter where you use the author as, you should be fine. All right, so you can go ahead and do that as you're putting into authorize, know for the more advanced situations like where we have related fields. So in the case of vehicles and in the case of bookings. All right. So let us look at bookings. Let's look at vehicles for us. I think vehicles, I'm doing fewer complicated things. So in vehicles, right. We know we have or page or injection of the client on their own time and authorize. Vehicles, if they're not null, then we load the table. Now in the table I have make model and I could have, you know, color. So let's add color. Actually this would be, well, let's not add color, no, but we could have had coloured of the point is that we have fields that we need to display that are related fields coming from another table. So vehicle naturally has made ID, but I don't want to display the make ID. That doesn't mean anything to anybody. Notice I'm not displaying any of the IDs. I'm only displaying the names and irrelevant data, so I have to say what the make dot name is and the model dot name. So that is how easy it is really to reference fields in the related table, right? So we're just printing, but these fields and everything else pretty much remains in tux like, Oh, we know it, it's the same loop, it's the same table CAM far much. It's the same kind of service call on initialized and everything. But we had to make an adjustment to data actually comes back when we call for the vehicles. So going over to the API, if I bring up the vehicles endpoint and go to the part where we get the vehicles. Then you'll notice that I made a few adjustments to our unit or four calls. All right. So both forget vehicles and get vehicle by idea just they did the same time because the need is similar. What we have to do is take advantage of the includes mechanism that we had put into the units of work. So remember, and I'm just going to do Control F 12, which brings me to the implementation of get all. Remember that we had included this parameter for a potential list of includes. And what we did was to say that if the includes IS NOT null, then we go ahead and include all the related data. All right, so here's a practical example of how this is used. So what I'm doing here in this API call is saying that when I make a call, when anybody makes a call to get vehicles, just automatically include the related make, the related model and the related color so that when that vehicle object comes back, it is easy enough for us to access the related fields are the fields from the related columns. All right, so I'm not using colors here. I could easily have been disciplined the color, but then I push the envelope to answer when I get one view correct card. I also want to include all of those details and I want to include the list of bookings, right? So remember once again, you see I'm just showing you how everything is connected. When we created our vehicle model, we said that we want the list of bookings are we want to know that there's a list of booking. So on booking, one vehicle sorry, has many bookings. If I wanted like a booking history on this vehicle to be displayed whenever I look at the vehicle. So I am seeing when you retrieve that vehicle, retrieved that list of bookings, I don't need them this stuff bookings every time I'm getting all vehicles because there might not be a case for that, but you could put it there. So that's all I'm doing really and truly. So it can mean that's I just rent a vehicle and while we're here, you can meet that. I just meant also to booking, right? Sorry to the booking API call. All right. So Booking has related fields also. So this is what we have know and what we're going to is modify it such that we're know including vehicle and costumer. And then when we're calling into are going to pass up that intrudes parameter. All right, and far booking. Once again, when you get to one booking, it's the same thing. We have our Lambda expression include. So the reason why I've includes colon includes is that we actually have quite a few parameters that could be passed in. We have that Lambda expression, we have the artery or below we have the stuff includes I don't want to put in the experts on I don't want to put you in that. I only wanted to put in includes. So with the latest versions of C Sharp, we can actually just specify the parameter that we want to put in and then put in the corresponding value. And because the others are notably it will just bypass and ignored them anyway. So that is what we want to do for both bookings and for vehicles. All right, so once again, when we look at our index page, sorry, when we look at our index page for our vehicles, that is how we are able to accomplish this. It no, for the booking, I'm doing a bit more so yes, I'm loading the booking. Yes, we're doing all of the rest of the things that we know. But then I'm displaying the costumer that granted the vehicle. Once again, we can add more details to the customer record. I didn't put in first name and last name. We can do that if you want. But for Nautilus, settle with the tux idea and contact information. We put in the date of the booking. I will put in the duration, which I intend to mean the number of days that this person had made the booking for. So in the for loop, the data that is being presented is going to look up differently. Yes, we have bookings. Well, this should be booking. So let me just make that adjustment. If I'm preaching it, then I must practices, right? So let me just make sure that my code is up to the same standard that time encouraging. So var booking in bookings. And then we say Booking dot costumer, dot-dot-dot society. Very similar thing to what we did with the vehicle, the mic and the name. Then we have Booking dot date created because that's the date, right. So we can safely assume that a booking was created on this date. This was the day it's all the booking date created. What I don't want the date and the time. I just want the date. So that's the date. And then we can push this a bit further for want and format. This will be like a tool, some format. So I generally like to have my day is the day or the day does in the 29th or the first or the second, the day, the letters, the mountain, as in the name of the month, and the four digit year are done. That should be double quotation marks. So this would be seeing something like the 29th of me, 2020. That's all we want, our display date. All right. And then for the duration, I'm going to say that I want the pretty much this math. We can do this math with due dates, right? I can say Booking dot date in, which would be the higher deity because you bring but in the car after you took it out. So the data brought it back in mammals the day it took Ito's, I didn't wanted to total days between those two dates and we want to cast that to a string. All right? And I just realized that I need to actually put all of this in one big parenthesis because of how arrays of pages work. So the way I had it, just know if we only had this between parentheses, then you would actually see this value printed out and the literal string dot to total these dot two string, which is not what I want. So I want all of this because all of that's a C-Sharp code. I'm going to wrap all of that in parentheses so you can see the yellow markers I were to C-sharp quote, starts and ends. And I'm willing to put the semicolon inside of that parentheses. And that's what's going to get me back the string representation of the total number of days, which will be the duration. So you could quantify this, are quantify it and say duration in days if you want, that's fine. And then everything else is pretty much in keeping with the same standard. And then we go a bit further and then we have our code bits doing the same thing, retrieving the bookings, doing all of that delete logic, and everything up front. All right, so you see it's not hard to transfer that bit off knowledge outside of us getting fancy with calculations. And maybe just doing the extra bit to make sure that we get the related data, which is really easy for us because of how we constructed the data access layer. Apart from that stuff, It is pretty basic and standard hole to get Bach data from the API and holds a structure it in a nice, user-friendly manner. When we come back, we'll look at making our view button work. So this person button, our first link in every 10 for details tables. It, it serves the purpose of making our record display by itself on its own components. So we're going to set up another component or we're going to call it view. And we'll see how we get to lower component, accept apartment or unused up perimeter to infer what data should be on the page. 26. Setup Create Form - Part 1: Hey guys, welcome back. So we're going to move on to creating data in this lesson. And the reality is that yes, we know how we see data, but that's really default data. The reality of the situation is that when users are interacting with our app, they need the ability to create data. So we're going to have to give them a form that allows them to fill it out, submit the information storage and the database, and display it to them accordingly. So we're going to start off with vehicles in the previous example, I start off with the less complicated one and then give you the chance to do the more complicated ones. And then we compared notes in this one, I'm going to start off with the more complicated and then you can transfer that knowledge in dealing with the less complicated ones. So the reason we're going to start off with vehicles is that we have to display the mic, the model, and we have to display the ability to the user to input those data points when they're creating them. And we already established that these are related. The, these are related data points going from other tables. So evidently we can't allow the user to type them in. And they'll have to do drop-down lists and such. So because of those more complex situations, we're going to start off with the vehicles and then you can try the others on your own and we just compare notes. Now, you notice that my interface is a few changes. One, I input this button or I inserted this button in the code. And it's really just a button with btn secondary on it and a plus sign. I'll show you the code in a few, but also the table. What I did was remove the table dash responsive class from it. So now it just stretches right across the screen anyway, which is more like what I would want. So you can meet that's adjustment if you so desire. But let us take a look code for the button. And we see here that it's really just an anchor tag. I have the HRF being equal to slash vehicles slash creates. So that's our component that we need to create this time around. And the class btn secondary spun off or dash plus and create vehicles. So once again, it's your application you started at all, you feel the need to, you experiment. It's up to you, but we'll just continue on this soul. What happens when I click the button is that it goes on for two pages is some, sorry, there's nothing at the centrist, there's nothing there because we need to go ahead and create the component that it will navigate to. So let us get started on that. So by now I'm sure you know how to create a component already created it, but just as a refresher, you can right-click, go to Add and then series or component and we're calling it creates the arrays are so you can go ahead and create that in the vehicles. And for every other page or, you know, create Piazza we need, we just, just do it in the respective folders. So the first thing that we want in this component and I created it's unclean everything out of it. So you can just append what I'm about to show you to the default content of the speech. We have the page navigation on top to let it know that it can be gotten tool through this address vehicles slash create. I'm also going to inject my HTTP client, as well as a navigation Manager, which is just a library that helps us to navigate between components in our blazer up. We're going to modify our h3 tag. And I'm just going to put the same card title class to it. And it's going to say create new vehicle instead of just create. And then we're going to get into the meat of it. Of course, you know, you have that quote, which I will just put there. So this is basically what your component needs to look like at this point. So when we talk about farms, you need to use the built-in component given to us by a blazer called Edit Form. Now this edit form takes a few parameters. One, it takes parameters are our attributes, well, a model. So basically this is saying, what should I want datatype, should I use to infer which fields I'm supposed to pay attention towards a form. So if we're creating vehicles, then our model needs to be some form of vehicle object or vehicle values. So I'm going to say at sign vehicle. But then of course you don't want to have any object by the name vehicle, so it's going to lie to operate. To remedy that, I'm just going to go ahead and create that object down here and initialize it to a new instance of vehicle at the same time. And then we see that that red line goes away. So now it knows that okay, it's dealing with vehicles. So look here to see whatever data points it needs to pay attention to. The next thing that I wanted to point out now would be what happens or what should happen upon a submission. So we can see that we want on, on invalid submit event, we want an onsubmit event. I want on valid submit. So what do we want to do when the data doesn't meet the requirements? What do we want to do when somebody clicks submit in general, and what do we want to do when somebody clicks submit? And there are no validation breaches pretty much. So that's what on valid submit me. And so I'm just going to work with unvalid submit. And then I'm going to say that I want you to call this method called create. Now once again, if I'm making reference to this method, I need to make sure that it's in quotes. I'm going to go down and then create that method called create vehicle. So you can go ahead and do that. That line goes away. This one, however, is there because it's not doing anything, but we'll soon Remy did that. And then we can start putting in the different parts of the form. So the top two components that I'm going to put in the form our tags would be for the data annotations validator as well as the validation. And so now we're not paying too much attention to validation just yet. But the thing is that we have data annotations that we can actually put over models, but right now we're sharing the models with the database. So later on we'll see why it's a good idea to kind of have them separate. But Farnell, whereas sharing them and we'll keep it that way. So data annotations validator won't be the most, it won't do much right now, but we'll put it there for later use. Validation summary means that if we try to do a submission and they're invalid data points, then this will kind of show this is required that doesn't meet this, et cetera. So these two kinda work hand-in-hand, but when we start focusing on validation later on, then we will see them in better axon. Know what we want to do is create our farm structure similar to how Bootstrap would have formed someone to say div class is equal to form dash group. And then inside of this form-group div, I'm going to have a label. So the first loop is going to be for the mic. And then sorry, we know that for the mic. We don't want a text box. You want some form of select the drop-down list, select list. So what I'm going to do is I'm just put this in another div and then I'm going to use a select tag and others open and close. But then inside of this select tag, I can say bind is equal to and what do I want to bind it to? It's going to be bound to the value oil to the model and the value in the model, we'll be meeting ID because this is for me. So I'm binding this let list to the mic ID, right? And of course, in keeping with the fungi, we're doing a bootstrap form. I just give this one the class equals formed. So the next thing that we need to take note of is the fact that this is an empty slot lists where the options coming from. So if you know basic HTML, you know, you have your select, then you have options, options, options, of course, we don't know what is going to be in the database. So we have to meet this option listing as dynamic as possible. So we need to look to the database, aka looked through the API to give us back the list of mix. And then we can use that to dynamically generate what the options will be. So let me just go down to the code section and I'm going to initialize an object of type list. So list I list. I can use them interchangeably. I've been advised that that's probably not the best thing to do boats in this situation. It's fine. So we can just say I list mic, I would call it mix. All right. And then we do want that when the component loads or the page loads, that the mix will be filled and ready for use by the interface. So just like what we had to do with index when we had two, let me just jump over there. We had to say on initialized, I want you to go fetch the list of vehicles. I need to do something similar and create uninitialized go fetch the list of mix. So I'm just going to copy this. You don't really have to copy it, but you could retype protected Async over a task on initialized async all over again. And what I'm going to do is instead of looking for vehicles, because I just copied this from the vehicles index page. But instead of looking for vehicles, I'm looking for mix. That means I'm doing client. Yes, HTTP grants off client.connect from JSON, erasing the list off mic. And my endpoint here would be mix endpoint. There we go. All right, so a null, basically when, when we are initialized, we're going to call the mix. So I need to fill this with the data once the mix of being retrieved. So what I'm going to do is put in a default option that says select the mic. So the user knows that, okay, you need to select the mic, fine. But then I'm going to see and start with the at sign if the mix is not equal to null. All right, so mix or object here, which is the list of mix. Here it is null. We went through this, just know with the index. So it's going to start off as null, but then it's going to get filled eventually. So if it is not equal to null, then for each, let's say me, that comes back. Instead of mix, I want to create an option, right? And the value for the option will be outside me dot ID because we want to track the ID. Remember that when we create the vehicle where really store in the mic ID, not the name. That name is what we want to display however. So in the section for the discipline went to see display the mic dot name. There we go. So it's going to generate as many options as there are mics for selection from this drop-down list. And that's really it. We just created our first drop-down list. Now we have one don't and three more to go because it's the same thing for model and it's the same thing for color. They're all stored in database tables, which we need to dynamically load the contents of when we're dealing with this form. So what I'm going to do to make matters easy is just replicate this structure here for the form. So on was MC. This one is going to be model. And I'm just going to basically change out everything that's said MC ID, I'm going to save model dot ID. This is going to be models, models, and this will be common models, models, sorry, and model.py, model.py name. And where are you going to do the same thing for color. So I'm just doing some express changes here to expedite this operation. So colors, colors, this is a common seed color and we're just making those changes quickly. So no, we have made provisions for the mic drop-down list, for the module drop-down list, and for the color dropped on this. Red lines however, are indicating that one we need those respective objects. And two, we already know that we haven't set up any API calls for them. So to just complete this operation, we can put in the line for the models object as well as the colors object. And then the same way that we had to make sure that we did the API call to initialize mix. We have to do that for models, and we also have to do that for colors. All right, so pretty much just fix that. So pretty much models. We'll await the client call to get the list of models from the models endpoint, colors doing the same thing, list of colors from colors endpoint and mix the same thing. Alright, so that's it for the drop-down lists. And really, truly that was a more complicated one. But you can see that if it did it one time, you can do it for the others. Alternatively, for the select, there is actually a component in blazer called input select, which works pretty similar. And I didn't say party similarity, but instead of buying, we have to say bind dash, value. Alright, someone to leave one as the input select, and I'm going to leave the other two as a select. So this was our original code. This is using the razor component and then this one is mapped to the original code. But we're just going to complete our form. And then we'll see how everything works on ties to together. So our next field that we would want the user to enter is maybe the year of the vehicle. So I'm going to follow the same format form group and then the label and then a div that's going to have my inputs. But then because year is an, let me just correct these uppercase Bs, right? Because year is of type integer, I am going to use the input number component, right? So input number by n value vehicle dot year. And then you don't want to say, I'm putting in this new, new section here that says validation message for, and then we open up or is a syntaxes see vehicle dot year. So actually we could take this validation message and apply it to all the others. Because the point is that we need some form of validation to make sure that this valleys are selected. Once again, we're not paying too much attention to validation, but I'm just putting them in from null. So I'm going to save validation message for. And then we have outside open parentheses and then open and close Lambda arrow vehicle dot and then the field name. So that one is for Meek ID, this one is going to be for model ID. This one is going to be for color ID. And then this one is for the year, like we see. Alright. The next field would be license plate number, once again following the same format. And this time we're going to use input text and we're still the value, but this time to license plate number. Alright. However, validation message for so I've license plate number we have year I think next stop would probably be the vehicle identification number or VIN. So that one is next. So form-group label, input text because our Vin is a string. And then to top it all off, I think the daily rates, they're intolerant, so I'll just put that one in and then rental rates once again is double. So input number is that one. All right, but the point is that if you just open the angle bracket and write the word input, you'll see all of the different options are built in components available to you have checkbox, date, file, radio, radio button, group, input, text, area, et cetera. So all of those components are built in to the forums and are available for you. So in our situation we used what, 33 different ones we use number, text and select, and that's fine. Now let's move on from our design and focus a bit more on what we want to happen once you submit. So of course we need a submit button because you have all the fields, but we didn't put in a Soviet. So my Submit button, just a button type submit and put it in the class meeting and beaten Dutch success and meat industry block create vehicle. So it's just a simple enough button, but then we need to do the logic don't here to make sure that once it, once it is clicked, it calls this logic and actually goes ahead and carries out the mandate. So let us explore what needs to happen here. So remember that when we're creating data, we need to make a post calls. So I already have the model that needs to or the object in any Submit Postel to the API effectively creates the resource. So what happens is that it starts off empty. It, it sets the context for the form, but then whatever data is put in it, That's why we have that bind. So whatever data is being put in along the way, we'll actually just get boned to the same object and then onCreate would have those values. So what we need to do here would be to await client call to our post as JSON async. Once again, there's a method per verb, so we've looked at the gets nulled. We'll look at the post. Where are we calling? What we're calling endpoints, dot vehicle, endpoint. And I'm going to be passing up vehicle as the object that needs to be posted. All right, then after it is created, we would want to go back to our index page. So here's where we can now use this NEF Monaco. Just collapse that. So now we can use the NEF manager and say Enough manager dot navigate to. And then we just see, sorry, we just say slash vehicles slash. Right? So let's us take all of this, work for a spin and check it out. Alright, so I'm loading on my form and I'm seeing some glaring mistakes here and that's no problem, that's fixed them together. So firstly, this should be, this should be more contexts, but I didn't have enough discipline to go through and say Select model, select color. Also, my controls need to look like the Bootstrap control. So let's start them together because if you have the same code I have, then you would also be seeing those. If you didn't fall into my traps, then kudos to you. So for the select, for the default selection, I'm changing them to select a color for color, select mic for me. And I'm going to put this bootstrap class, which is form control on every one of these other components to make sure that they all share the same styling. So with all of that done, I see just a few cosmetic changes. Let me just restart. And here we are. So this looks much better. All right, so let's select, OK, here's our drop-down list with our mix from the database. So Toyota model. Okay. Prius color, it's black. It's 2020 model. The license plate number, someone to direct the lessons with numbers similar to what we would have in Jamaica and the VIN. Well, that's often numeric, so I don't think after, you know, be too strict with that. All right. And then for the daily rate loans, again, within the context of Jamaica, you're probably rent a car for $3 thousand a day. And then when we click Create vehicle look, it navigates tool or index page, and it is here for us to see. All right, So we just effectively created our first resource using the UI as opposed to the API like we did in the past. So I'm going to encourage you to take that knowledge, transfer it to the other ones. So you still have to make sure that the persons can go in and maintain the list of mix because we already know you can see them. But we can see and delete retina. We need to be able to create cm formula models, same four colors for customers as well as for bookings. All right, so bookings, we can review bookings together later on because that one might take a bit more fitness, but essentially go ahead and transfer the knowledge and do these. And then we can compare notes only comeback. 27. Setup Create Form - Part 2: Hey guys, welcome back. So you got an assignment and I hope you completed it either way we're going to go through it together. So the challenge was transfer the knowledge that already garnered from sitting on the vehicles, create form and go ahead and set those, create components for all the other resources we want to allow users to be able to enter. So makes models, colors, vehicles, customers, and bookings. Well, we did vehicles together. So just as a quick review, we could navigate to the vehicles component. We have our drop-down lists which is dynamically populated with data based on what's in the database. Courtesy for API. So make model, color. All of those are API and formed. And then we have our input number. Input takes an input number. So we saw that we have the different input components given to us through plays or out of the box. And how we can kind of customize others using the HTML selected or the select tag given to us by a blazer. Now what we want to do is go through the other screens together just to make sure that we're all on the same page. So I'm going to start off with some of the easiest ones which would be mixed models and colors because all that's really there in that form is name. All right, so another mic would have been WWF told you to put in Nissan. Let's test create mic. There we go. Now we have Nisan in the list. So if we just go back and review the code for that, it looks pretty identical to vehicles at the top parts where we have the page with the path makes slash 12 hour HTTP client and nav manager be injected or little tag at the top so people know exactly where in the application they are. And then we have our edit form, which is using the model of an object called meek. And then we know that we have our main object being initialized in the code. And then on valid submits, we have creates mic, which we also have in the code. And then we have our annotations while the data and validation summary. Then we move on to say input text and bind dash value, make dotnet. Alright, and we give it the form control and have the validation message. And we have our button. That's really it. Now, the uninitialized method is actually empty and arguably we could do without it. I mean, it's not doing anything. We didn't have to retype it. But just in case there's anything you want to do right before the page loads or as the page loads, you can always put this method in. All right, so I left it there in all of the components just in case, but just letting you know you could have it not doing anything or for a cleaner, arguably cleaner code, you could just omit it since this is really just an override any way in create mic, go on to say awaits client.read post as JSON async, and recall the appropriate endpoint passing of the object that we want created, then we navigate back to our index page. Now, that is the general theme for models and colors. So just looked up makes, if we look at models and we'll look at colors, it's pretty much the same quote. Literally, copy from me, click, Create, and then paste over in the next one. So this one would be performed models and all I did was Control F and find all the things that said MY capital M with much case on and change them to. And model, and I did the same thing with lowercase mic and lowercase model. And with that, I didn't have to change any other code because everything else just fell in line because the fields are pretty much the same and it's easy enough to replicate. So that's the same thing for model. And once again, the same thing for color. We're going to color slash create, and everything else looks pretty much the same way. All right, so the, the models clearly are different for the different Create Pages. Now let's look at the create customer forums. So on the new customer form, it's not too much to worry. A boat we have tucks, identification number, e-mail address, contact number, as well as address. Now, one thing to note, make sure you're using the cart component relative to the cart datatype because even though this is tax identification number, it says number, but the reality is that in different territories, this number might just be alphanumerical, are having special characters. For instance, in Jamaica, we tend to use dashes in between our numbers. Alright? So you just want to be careful that you're not using their own field for that datatype. Either way, let's just go ahead and create some book customer actually have created this customer already, but I'm just going to do this and create customer. Say see, here we have our customers being displayed. All right, so let's take a look at bookings. So Booking though, left for last because it's arguably had the most complicated bit of code. But I'm going to gloss over the customer form just so you can see exactly what was done. So we have each form section, input text for the tax ID, email address, contacts number, or address, eras input text area. Say you don't want to start this kind of bigger than the regular text box because it just takes era. And then the rest of it is pretty much in keeping with what we've seen. Otherwise, no one would go over to booking. We see a different season. One. It's a drop-down list for the vehicles. But notice how I'm listing all the vehicles. I'm listing them out basically by their name, right? Toyota Prius. And then I put up there and that's the license number. Could have put more details, but let's just work with that for null, the customer, we put the dots ID a pipe and the email address for said customer and then the date, notice that it is actually displaying today's date, the date as at the time. And then we have that Callender control that allows us to change it. And this calendar will look basically the same in any chromium based browser. So this is Internet, sorry, this is Microsoft Edge. You will the same way in Chrome, but it might look differently in Firefox. And while I'm not entirely sure about how it might look in opera, but the point is that it may look differently across the different browsers. So you'll want to pay attention to that. But the point is that the calendar control is given to us courtesy of that component or the type that it infers, right? So let me just show you the code that is behind this rendering off the farm. So once again, general layout is the same. Once again, consistency. After a while you start realizing that you're repeating things like, you know, every time we have to tie this h3 class and see that, that, so you might think about making this a component of its own. I would just call it a component and probably pass in whatever is unique. So that way if we wanted make a change to how we show the title, we don't have to do it 20 different places, but we'll do that later on. So I'm just, I'm just giving you ideas of how components can make your life easier. So back to our form. We have our Edit Form Based on the booking web or valid submit function, which and what we've seen, no matter how complicated the form is, the unvalid submit is pretty much the same all the time. We pass it over to the API, and then we navigate our way, right? But then let's pay attention to what happens here. So one hour drop bonus for the vehicles. We know that we are to go to the API and then where to get the list of vehicles. So we're familiar with that based on what we did on the vehicle speech this time where getting the vehicles though. But then for the actual drop-down lists, sorry, wrong one for the actual drop-down list era, we have vehicle ID okay. Where binding to that vehicle. And if the vehicles is not known, then for each vehicle in the list, then we want to generate an option that has the value of the id of the vehicle record. But then look at what I have put in the display section. So I'm just displaying various details of the vehicle. Then make the model dot name, and then I have this pipe and then license plate number. Alright, so over you want to lay out the data to the user so they can know exactly which vehicle it is, because probably it would be useful to even put the color somewhere in there. So it would be black Toyota Prius or blue BMW X5 on the sun. But that's up to you. But I'm just showing you what, what I did, right? To get the more complex kinds of displays, it's really not that difficult. And then in the customer section, very similar, we had to go get the list of customers once again from the APA, fill them, okay? And then for each of them we generate the option with the customer dot ideas of value. And then we're displaying the TOC, say the separator and the email address could put in more details, could put in fewer, right? The point is that it's your application, you want to make it as user-friendly as possible. But once you understand how to manipulate your data is the most important thing. Now for the date, notice that my own is displaying today's date. I'm not sure if you're one is you probably just got that default data of 0 on slashed 01 slash three zeros on the right. The reason for that is the datatype we're using is of type date, right? It's the time. So he did oh, it is of type datetime. By default I did. Time cannot be null. It has to have some form of DID. And the data you're probably seeing is the default one. That's not very user friendly. So. What I did was when declaring the object to be used for the form as a model for the form, I, initialized data ought to be datetime dot-dot-dot, dot-dot-dot. So whatever, you know, datetime dot now gets a exact timestamp as a null. What I don't want the time stumped. I don't need the 12 PM or whatever. So I'm just saying give me at D8, the level of detail you put into it, that's up to you. No problem. Once again, your application, your needs might be different from what I'm expressing here. But once again, I just want to get the foundational concepts across. So I'm initializing this object that we can do that at any point we want the form to load with data, we can tell our object POV, this bit of data so that by the time it's boned up here, any field that has that bind will automatically display the corresponding data that was preloaded. Alright, so that this whole I get that date to be displayed and amusing an input date component, which is why we get the Callender. Alright? And then outside of all of that, we have the basic create booking where we just send it across to the endpoint and navigate always. So let me create a booking for this customer who is renting all tar Toyota Prius create the booking and I'm getting on her. No problem. I really didn't test this before this lecture. So let us inspect this era to give us a can always right-click go to Inspect. Go over to the console of your browser. And then we'll show you what the arrow is. So here in reading the air at sea and that there's 500 response on the stood. And then you'd see in that it's happening line 63 of our index dot arrays or pH. So it's line 63 of index.js are, let's see what and that is our API call for our index page. No, we're not entirely sure what the issue is. And if we check, we saw the message in the browser didn't give us much help, but we do have this output window that we get access to. Basically every time there is debugging going on, right? So Microsoft or dotnet Core is actually always logging to this window. So if I scroll up just a bit, start seeing the same areas that are even more errors are more error details then what the browser was displayed to me. So this is a nice way for you to know how to debug your applications when you're getting these kinds of errors because it worked before and know it stopped working. Why did it stop working? So it say something here, a boat, an error and exception occurred while calculating database era content. I'm not sure if that is it. What we see here, the same thing that was in the browser. If I continue scrolling up, then maybe see more details. I start seeing some things. I bought JSON, JSON serialization and I'm going up and going up. And then in the start of this stack, trace is a possible objects cycle is detected. This is due to something, some reference on there. So I know this message, I know exactly what's wrong. It doesn't necessarily tell you what the issue is, but I'm going to walk you through this one. All right? So what happens? And I'll just get a lot of debugging real quickly and jump down to our object for booking. What happens is that there might be times when we're trying to retrieve objects and include additional details. But the additional details are the additional objects we're trying to include, has, relationships are should contain objects of the object. It's confusing. So that's what they meant by a cycle. Some cycler reference arrows. So booking contains a vehicle, but then vehicle contains a list of bookings, right? So basically it's getting confused because it's saying you want a list of bookings. You want to include the vehicle details, but the vehicle details includes a list of bookings also, so it might get confused, and that's a common issue with APIs actually. So generally speaking, we solve this using this library called Newton's soft. So I'm just going to right-click on our server project and we're going to go to Manage NuGet packages. I already have the package installed, but what you're going to look for is Newton's soft. And just let that search and then you want this one Microsoft not is speed dotnet course our ASP NET Core dot NVC dot Newton's soft JSON. So you want to just click that, that don't load. Well, you'd see install or you see that black arrow already have it. So that's why I see the red X. Go ahead and install that. And then once that is done, then you want to go to the startup file for the server project. Go although all the way down to this line services dot add controllers with views. And then you're going to add the following code. Dot add Newton's soft JSON. And then we're going to give it some initialization and options are going to see o p with our Lambda error, sorry, Lambda arrow. But, and there we see o p dot Syria, Syria, sir serializer settings. And let me just go to the next nine so it's clear what's happening. All right, mate more smith. So Sara Lazar, settings dot reference, loop handling. So that's what's happening. It's causing our reference loop. Alright, so reference loop handling is equal to and I'll just go and see Newton's self.age JSON data reference loop handling dot ignore. All right, so in other words we're seeing yes, you might end up with our reference loop though, make a big deal about it. Do what you have to do and get bought the data. So that's pretty much what this is going to be telling the API that is in our server projects. So let's Australia, that's like some browsing to bookings. And of course, you know, we have to login first. And then after we log in the moment of truth, so K vehicles sorry, I did say bookings and there we go. No, we're seeing our bookings with the appropriate details based on what we intended to list out on the index page. So that is actually a very common error with APIs. It's a good way. A good worker owned. Newton's soft has really done well to manage that error. So here's the code. Once again, we just added this to the pilot said add controller with views. If you're only using an API that you probably only have AD controllers. As the method here, Services dot-dot-dot controllers. It's the same thing. You just tack it on to the end of the parentheses and it should work. So at this point we've hit a milestone where we set up our create forms for all of our various resources. So now you know how to allow the user to input data through your blazer up and storage in the database. Moving on from this, we'll look at how we allow them to modify the data that has gone in. Because when we look at the booking, we would see that okay, there is a date in and update old retinol. All we're displaying is the data out. As a matter of fact, I had actually commented on this column here that would be dead in minus 0, 2, which I know is going to cause a problem because when we refresh and attempt to reload the bookings page no. Showing the missing column, look at what you're seeing. So that's not a sensible value right there because the Dayton has an coma Xia time, we know that it's going to default to the 0 1 slash. So when it is doing the calculation, it is going to give us a negative since that date up until the day that we had. So that is going to be an issue. Either way we can fix that cosmetic because we can easily put in an if statement to see if there is no date in coming from the model, then display something else. Otherwise display the duration in days. Not withstanding that though, we need to set up the edit form because when somebody brings the car, they need to update the existing booking record with the return. Otherwise, we do need the edit for all of the other ones. So we'll see how that works out in a few. 28. Setup Update Form - Part 1: Hey guys, welcome back. So in this lesson we are going to be looking at setting up the edit or update form for our application. So in this lesson we're going to be looking at a few things. One, how we can create reusable, actual reusable components, and to how we can implement parameters and 3, how we can implement what we call event callbacks. So the genesis of all of these things to look at in just a simple edit operation would be the fact that an edit form looks exactly like a Create form. And I don't often times you're going to have the same fields. The operations will only differ because one is creating data on one is changing existing data. However, as far as the farm is concerned, generally speaking, you're going to have the same sets of fields that you use to create that you want the user to be able to change. All right, so we're going to start off with a simple one and I'm going to use the mics create form, right? So what we need to do is create a component that has this form in it to begin with. So I'm going to right-click on mix and I'm going to go ahead and add a razor component. I'm going to call it farm components, nothing too fancy. All right. And then I mean, I hope that's self-explanatory. It's a component for the form. And what we want in this form component is the actual edit form. So everything that went into the, into the edit form that we put on our Create component. We want all of this, at least that part, the reusable parts to be in our form controllers, farm components, sorry. So I'm going to remove this HTML and replace it with the edit form. And everything is pretty much remains the same. But we also want to specify certain parameters for this component. Meaning we can set up our components such that when we call on it, we pass in values. So just the same way that I would edit forum, we said model equals something on valid submit equals something. These are really just parameter values that are baked into the edit form component. So my component, which is farmed component, needs to have a parameter. So open square braces write the word parameter and then I'm going to say that it should take a parameter of type mic with the name mic that's going to correspond with that model that gets passed in. All right, Next parameter, we want something to determine the text of the button because this is a reasonable farms, so I don't want it to say create me all the time in case I am actually editing. All right, so we want to contextually define what takes, gets printed opened up buttons. I have a parameter named button text, which is of type string. And it's going to have a default value of save. So that means if I don't provide a value for that parameter, then it's just going to say Save, otherwise we can override it. So I can know, replace this static text with the dynamic text being said by whatever Valley gets passed in. And once again. This is setting a default value of C if no value is passed in. The third parameter I'm going to have is one called on valid submit. And this one is going to be of type event called Bach. So this is like an event handler delegate to see, okay, what method should I call in this in the place of this. So unvalid submit, that's what I'm calling the parameter. So I'm going to say unvalid submit is equal to at sign on valid submits. So that means when somebody calls this form component, they can provide a mic object. If it's empty, we want to assume that they are about to create one. If it is filled, then we assume that they are about to edit one. Alright? If they pass, they can see, well, when I'm editing, I wanted to say Save Changes. If I'm creating, I wanted to say create, whatever it is. If they don't prevent this one, we have a default value anyway. And then this parameter is seeing what method should I call. So whatever method name is passed in here, that is the method that unvalid submit we'll call. So that is our forearm component. Now we have a bit of refactoring to do to both the edit, well to our creates what let me set up the edit page first so you can see exactly how it ties in. And then we can go back and modify our creates. So in the same mix, we're going to go ahead and add RAs are component and we're going to call it edit, edit dot, razor. Alright, and then we go ahead and inject the usual thing as well as defined our page root two. So pH is equal to slosh MC slash edit. And then we're specifying here that we expect a parameter. So this id colon in DC and I need a parameter which either referred to as ID. And it should be of type int. All right, so there's a keyword parameter, so I need to tell this component once again, That's it needs a parameter and I'm going to call it parameter public int id. So this property name has to correspond with whatever name I'm defining at the top here. And it would just set that to get and sit. All right, next up, I need to define me. So MC or an object of me rather is equal to a new instance. And then the first thing I need to do when my component loads is to fetch the required That's his abode to be edited. So remember that when you're editing, it means that data exists. So that means I need to go and get the record with the ID that was provided cause the person would have clicked on one and said, I want to edit this record. The ID is five, we need that red card, so I'm going to put in protected is seeing override over for the task on parameter. Sit is saying, alright, so protected Async over a task. Parameters set. It seems that that means once that parameters provided, what should I do? So notice that in the previous ones we probably had on initialized, so it's not being used here. Okay. Well then on this situation, I don't want it up in uninitialized, I want it up and when there's a parameter sit, All right, so on parameters set is sink. What do I want to do? I think I'm missing an S here. Perimeters set a seed. There we go, straight in. So there we go, Just get the spinning card on parameters, sit async. So once I want to do now is fill my mic object with a call to the can I int dot, and then get from JSON is sink was I wanted to get the record right and I want it to serialize as a mic. And then I'm going to call endpoints dots. And this is MC, so it's the mic endpoint makes endpoints, right? So that is our endpoint that we're calling. But then I needed to pass over the ID also, right? So that means I need to kind of format or apply some more finesse to this endpoint. Because remember that our GET endpoint, let me just go over to mix and show you that gets endpoint. Once again, we're looking to get this one. So either it could be five, right? So we need to be able to call this particular endpoints. So to format it, I'm going to use interpolation. So I'll assign and wrap these in this party in curly braces. So we're calling the end point. All right? And let me write their goal and then slash, because I don't have slashes on the endpoints. There we go. Remember we removed the slashes, so we say slash. And then I'm going to pass in the ID value. There we go. Alright, so similar to how we modified our mic and I need to close my quotation mark. There we go. The next thing I want to do is define what should happen after we click that button. So remember we haven't started looking at the visual power, just coding up the events stuff. And then I'll show you how we can leverage this component art. I'm going to call this one async task, edit me. All right, so when, when, when we click Submit on the edit form, I wanted to call edit make. What do I want to do? Well, I'm going to say, I'll wait my client call to put as JSON async, and sit. So client has ever verb. What am I putting? Well, firstly, what is the URL? So my URL would be endpoints, dot mic makes endpoint. And then the data that I am putting o would be the next parameter, which would be make. Alright? Because remember we're dating, so I have to provide the object with the data. We just got the object. You would have been edited and know that click Submit, we're going to meet this call and say perform a PUT using this data on that endpoint. Right? After that, I want to navigate someone, just say, sorry enough manager, Dots, navigates tool and then just navigate home. Just like what we did on the Create. Alright, kinda straight forward. Once again, we are accepting apartments are called ID and this link, this URL or acquires that parameter. We define or mic object and initialize it. And then we fill it wants the power meters are ready for use. And then we go ahead and do our edits. However, what about the visual stuff? We still haven't done anything other than this h3 tag, right? So for the form, I can call my farm components, right? So yes, when edit form, but like we determined, edit form is really just the built-in forum where the data validation and annotations on such, we have the fields and then we have the button. All of those things are common between the edit and they create. So we put it in this form component and now we can call formal components and look at this node. I can provide values for our button text and unvalid submit. Remember those are parameters that we said we wanted right button text and on valid submit. So let's go step-by-step. So button text, maybe I want my button to see the right. And then for the unvalid submit, I need to provide the function that should get called once we hit the button. So unvalid submit, you know that once we hit the button it's going to go to unvalid submit and call whatever function we put here. That's what it does in the create. If we just go back to the Create, that's what did those red on valid submit creates mic. It jumps, don't and goes here. That's hard-coded. I needed dynamic because I don't know if I'm creating RFM editing. So from the edit eraser component, I'm calling this dynamic form component and this dynamic, this parameter. I'm going to tell it that I wanted to call edit mic. So that is the method that I want this form component to call when there's a valid submission. And then the last parameter that I need to provide is make, because I did see that. Let me find it again. The model is going to be equal to at sign mic, right? So it's expecting some mic or some environmental value of type mic. So I'm just going to pass in the very meek that we feel don't hear, right? So. This was a MC equals MC. And then I'll just close this parameter, get rid of all those errors that may put on the outside and they're right. There we go. So put on our ads. However, make me and our update. All right. Let me just double check that I had a link to the edit on. Yes, I did. So mix slash, edit slash. And that's why we pass over the mic ID once again because we defined it to take that parameter. So let us stick or edit for a spin. All right, so where it's our list of mix. And I'm just going to create brand new one. So this one was supposed to be Honda, but we made a mistake or a rotunda over the iPhone. No. That's okay. Let me think of something is that we don't yet have Jaguar. Alright, so it's jaguar. Jaguar, so I need to edit it. So I'm going to hit my edit and look at where we go. So this form identical to the create form, it doesn't make sense. We write this farm twice. All right? I mean, maybe the situation may require it. And if it does, then the same principles you just used on the create form, you can reapply them on the edit form, the edit form tag, and you know, all of the fields that you need and everything fine in this situation, I don't need, I don't want to have to write them twice. All right. So I'm going to just change that update and look at that. Okay. It didn't work all toll she were expecting it. Let's take a step back and evaluate. So I'm looking back at the code and I think I see what the issue is. We did not form this URL properly, so my mistake, let me just go back to the put, sorry, wrong file, but to the put method in the mix controller. And what it should have is the URL with that ID parameter. So that's what we did incorrectly. So let me just backtrack. And the URL actually needs to look just like this. All right, so I'm just going to use that and replace this makes endpoint parts of its slash ID because we have to pass in the ID value as it's used for some far off validation along the way. All right, so we're going to have to do that and then we pass in the data to be updated also. So let's try that one more time. So I'm going to go in, edit Jaguar, put on the r, and then we click Update, and there we have it being updated. So it was just a URL issue. But we see how we can use our reusable components to facility the edit. Now since it's sore usable, the point of it is that I can know refactor our creates PJ to use this form components. And the advantage of this once again, is that we have fewer police system maintained. Because if tomorrow we hear that there's another field that needs to go into the database. And of course, if it's in the database, then it probably needs to be in the create and edit screens. Then instead of having two forms to modify, we just have the form component. So for the Create, I can actually just remove all of this and make reference once again to form component. And just filling out the rest of the parameters I would have the button takes the mic, the mic being equal to me. Once again, this object that we initialized, notice it's empty, we're not fixing anything. So when it goes over, it has no data to preload into our component. And then on valid submit, we call the create MC method. All right, So lets us create one more meek and then edit it and we can send off from this active. So I'm going to go create new mic. This time we're going to do high on day create, make. Our ads are new. Form component is working for the create. And well, I should have put a spelling error to justify it. So I'm just going to modify it. Click Update. There we go. And then I said, Oh, I made a mistake. Let me modify it again. And let me do that again. Take all these extra ones and there we go. So no reusable component for our farm. So the challenge here is go ahead and make these similar components for all the other entities or resources that we'll need to maintain. And go ahead and refactor the Create and create also the edit to use that form components. When we come back, we can compare notes. 29. Setup Update Form - Part 2: Hey guys, welcome back. So in this lesson we're just going to be comparing notes. I'm just going to walk you through the code that I implemented and I hope that you also did it, but I'll be giving you, of course, gardens in case you face difficulty and walking through the code slowly enough that you can actually copied off if needs be. So let us start off with the easiest ones, which would be colors and models, because colors on models basically have as little data as mix does. So the same form component, stuff that we did for me X and then we reflect it or, or create and our edit to just use that form component is the same thing for models, right? For the form component, the only thing we had to change all was a fun. Now we're dealing with them model, right? Everything else pretty much the same. And then over in the Create, we see I didn't change the button text firm updates. I need to say Create model here. All right, it's a good, We're going through this review, but that component called is identical as is the one for the Edit. Alright, and then the code is pretty much identical. We're waiting for the same ID. We make sure our pH is going to whatever it is, slash, edit slash with the id being int. And we did that in as a parameter. We call the model to be edited. And then we go ahead and call our PUT with the models and point with slash ID with the model to be edited. And then we navigate back to our modules page. All right, so pretty much between models, mix, and colors, the only difference in the code is the actual class and the object name being used. The rest is pretty much the same. And also the endpoints, of course, no vehicles. All of the different series that it's a more complex form. So the form from Creates, we put it in inside of our form component. What you would also notice that I'm injecting the HTTP client. All right, Why am I injecting this trend? Because on the original form we need it to load up three drop-down lists. So all of that code from the Create, how do we not take in this route? We would actually have to repeat these on the edit page because both of them need that list of values up front. So what we've done is we've taken that code out of the creatine, will put it into the farm components. And a form component deals with preparing the form and all the data and needs up front, we still have our parameters for our data. The button takes as well as the event callback method, right? And on the create, our clients springs into action when we have to submit the data via post as JSON call, as well as on the edit page when we have to preload the data one and then submit the updated data. Once again, our endpoints change accordingly. So you see, we're putting it all together, making the application a bit more maintainable, fewer points of contact when there are changes to be made and where taken advantage of whole blazer allows us to be very modular in our approach in building any application. Customers. Pretty simple. Simple form was used, no extra needs for any client over here for any pre loading of data. So the create code looks the same way just with the forearm component right there. And the edit form is pretty much the same thing. All right? No. When it comes to bookings, we had to do a bit more. Well, pretty much full bookings are doing the same thing that we did for our for our vehicles, right? Because just the same way we had to preload the list of the list of vehicles and the list of customers in order to make a booking. So we had to inject our client into the forearm component and then do our uninitialized. So we took all of this from the Create component. Notice it doesn't have that uninitialized. It doesn't have anything to put it in the form component. And then we have our creates cord looking just like this, and our edit code looking like this. All right, so that's a quick run through it on to bore you to death explaining and over-explain because the concept would have been explained in the previous lesson. This is the implementation one of course, you can go through and pause as you need to copy off what you're not so sure about. But what I want to point out is that I created another components. So in my components folder, remember when we're fooling our own components, initially, creates a components folder and I created this sample one. Well, I created another one called the buck to list dot eraser. So let me show you where it's used. Generally speaking, if I land on the create or edit page, there's a chance where I might not want to actually create anything, our edit anything. So I wanted to just go back to the list. So then I would have had to replicate that button corridor across every single form and change the URL where I wanted to go with them when to use the anchor tag and manually type in the URL. Or I'm going to see not one click navigation manager go to that particular URL, right? So instead of repeating that code right across every page, what I did was I created a buck to list components. And then this takes a parameter called target. And then all I'm doing is putting in the specific page relative to where I am. So if I'm on the bookings form, then my buck to list would be for the bookings list. Right? And then that changes per components. So for the customers is the same thing just buffed to list customers. For which one is this one? This one is for the vehicles, is the same thing but to list vehicles. So lets us look at Buck to list. It follows the same kind of pattern as a component that requires a parameter and all one, I'm not navigating through its I don't have outside and pH as anything. I'm injecting my navigation manager. All I have here is a button which I've styled. I mean, this styling may not be what you want, but you'd see your application, you modify it or you feel. But I'm styling this button to be an online dark button, btn block. And I have defined that onclick event for this button. Alright, so whenever this button is clicked, it's going to go, man, called this method. It's taken the parameter. So we already went through parameters when we said TO form component, right? So I'm taking departments are called targets, which is why we can specify targets and just pass in that string. So when that button is clicked, we're going to come down to this method and see navigation manager and navigate to. All right, we've used those, that that method already we know how to navigate two works. But then I'm going to dynamically load up the baseURL of this entire applications and nav manage about base URI gives me the server basically. And then I'm going to put in the targets. It's going to say something that localhost colon, whatever port number you have, slash. So notice I don't have to put a slash here because the slash is implied through this value. And then I'm just going to the target as specified through the parameter. So let's just take a quick look at what that looks. So I'm going to go back to grow and 0, which is mix, alright, creates a new vehicle and I'm like, oh snap, I really don't want to create a new visa. I want to go back to this list, look at where we land backup mics. If I go to models, same thing, back to list, go back to models. If I end up on edit, I don't really want to edit back to list. All right, so that is how we can, once again make our applications modulo and not tough to repeat code too much across Windows creates a component. Give it enough parameters for, you know, to make it dynamic enough. And then we just plug in those parameters and into the components wherever we see fit. Alright, so that's really it for this review. Once again, if you missed any parts of fit or you had difficulty going through it, feel free to Bach. Bach truck through the video on pause at the different parts and review the code. Make sure you're spelling is squared and all of your references are correct. And when all else fails, you can always hit me up if you need further guidance. 30. IMPORTANT - Fix User Audit Fields: Hey guys, welcome back. So I have a quick fix for us before we move forward. And this is regarding those audit fields. So you probably noticed that in the database, all of the dates are showing up when we create. Let me just go ahead and view data on one of the tables that dates are showing up. However, our usernames are not. So these would have probably been done through the API. That's fine. But the reason we have created by an updated by would be that the logged in user in the UP would be logged as the person was touched the record, right? No, that's not happening. So we just have a quick fix to make and I'm going to make it in the unit of work safe again, the school but bone to the unit of work in the repository folder. And the original code that we have is var user is equal to HTTP contexts dot user, dot identity, dot name. No, the reality is that I probably got a bit overzealous in implementing this in blazer. Because this works in MVC, works in her Razor pages, where the HTTP contexts usually contains the user information, whether it's also indicated would be passed on in the context. And it's an easy way to just get the login name of the current user. However, in the blazer situation where we're not really doing work on the API, little we're doing into the client-side level. Or that's really being passed along is a Tolkien with the inflammation about who it is. So this HTTP context does not have r. It doesn't keep the logged in user because it really doesn't know who is logged in. We don't know who the client is. Or rather it only knows the client up. Which is really the inflammation from the Tolkien it really uses to say yes, okay, you can access the end point. So this HTTP contexts not use it up. I'd entity name does not work in this context, so we're going to modify it a bit. So I'm going to go into the mantle, the original code. And I'll already have the quote correction here, which I'll just walk you through. So the first line for the correction is that we're not getting the user directly where getting the user ID, because it does Constantine, it being the token. And the Tolkien, is already parsed out into the HTTP context. So we can drill down into parts of the token information through HTTP contexts, dot user. Then user is really what we'll call a claims principles. So claims are basically bits of information that tell us who you are, right? Claim I claim to be this, I claim to be that that's what the claim is. So the user object instead of the HTTP contexts is a claims principle, which is a collection of the claims of coming from the Tolkien being sent down by our blazer client said interface. All right, So HTTP contexts, dot user get all the claims and now we're going to find the first claim. So if I ever put this in debug mode and just hover, you would see that bearable 15 claims. And the one that contains useful information about who the user is. Is going to be found on the claim type name identifier. So we have a constant here called claimed types, right? So if you start typing that in, you might have to include a library for System.out security dot claims, claim types, they're just constants and name identifies one off those constants. All right, so that is going to give us the user ID pretty much. And then we want the value of that claim. So this cream or the user ID is stored alongside this claim type. So when we find the claim type of this type name identifier, get the volume, we get the user ID. Now that we have the user ID, I don't want to store the user ID because uses could get deleted in all ten years on the future. You don't want to have the historic telephone know which user had this idea at this point in time, is probably easier to store the user name, which is why we upped it for name up here, right? So I need to retrieve that user. So now I have the ID. I want to say var user is equal to our weight user manager dot find by ID a sink. And then we just pass in that user ID and then we get that entire user object. All right? This user object has everything about the user at this point because this went to the database and retrieve that red card from our speed that users table. So FirstName, LastName, anything that we had put into the application user is knowing this object so you can store whatever you want. I'm just making suggestions. Know if you've already typed user manager and you're getting arrows. That's because we need to inject user monitor as well. And well, you know, if we're injecting it, that would have to initialize it as usual, right? But then this is in the context of application user. All right, So User Manager in the context of application user give the object the name injected to initialize it, and then we can use it freely. Use a manager as a variable for library which has a number of features and functions for finding users on using inflammation at will. So after we know have the whole user object, we no need to say updated by Anne and I can see user dot. And like I said, you can get any information about the user through this object. So if you want to store the e-mail address, first name, last name, whatever it is you wanted to store, that's fine for me. I'm just going to store username. The username is the same as email address or not. I wanted to store the username of the person who at this point in time did this option. So anytime that happens, I know who it is and then it's excreted NO2, who it is. So let us just run a quick test to make sure that our fixed works. All right, Someone's noticed this with creating a new mic and you see I'm logged business test at blazer.com. So another mic off a vehicle would be, let's say fiat, sieve. Alright, fire is stored. Let us look back in your application. Go to view data. And now you're seeing that audit inflammation. So those missing for previous tests and no, going forward, it should be fine. Right. 31. IMPORTANT - Fix Vehicle Edit Issue: Hey guys, welcome back. In this lesson, we are going to be carrying out an essential bug fix. And that bug is centered around the vehicles and probably any other edit operation that has a drop-down list. So the current anomaly is that even if we modify this vehicle, if we change anything that we have to type, it will be successful. But then when we change the drop-down lists, nothing changes. So if I wanted to change this from black to blue, it would save everything but then still routine the origin of values. So we're going to be addressing that know the background to this issue has to do with the way we're retrieving the data when we're about to edit. So in it, threes or components, the code behind for it, at least when do we have the component loading, we get the vehicle now are getting operation in. Our API is actually outfitted with all of the Includes. So we're actually including all the details on what's happening is that these details gets included while the IDs may change the details don't. So on The put, it's really just receiving the new object with all of the original included details. So what I'm going to do in this lesson is introduced another end point. So we're separating get from Get details. So in the AI HTTP and I'm just going to walk you through the changes that I've made so far. So in the HTTP repository, I've introduced another behavior here that is get details. So we had gets them introducing get details, which is going to take the same two parameters as the get, the URL and the ID. And then its implementation will simply append slash details to the end. So it's identical to get, except it's going to specify that we want the details as opposed to just Get. All right. So once you've done that in the component, you can go ahead and, and you'd modify at least the view components. So the Edit component wouldn't change because it's already getting, that's fine. But then the view component, which is where we actually need to see details of whatever component or whatever object it is. We're actually going to say get details. So while this is specific to vehicles, this may also apply it to other objects that you may be working with. Our other relationships that you might be working with. If you're viewing the details of an object that has relationships and you need to get Buck included navigation properties are included details from other tables. Then you will probably want to split them all this. So now that we've modified that on the client, so let us look at what we need to do in the controller or controllers. Know I have specified a costume path, so we have the original get. And what I've done is to take out all of the Includes. So at the includes parameter that came courtesy of our unit of work, I've taken that out altogether. So it's really just going and getting the vehicle and returning just that object, no extra details or anything. However, when we see get details, it's going to call ID slash the word details. As a matter of fact, this endpoint would actually look something like this when it's tapped. Also it would be api slash, slash 05 slash the word details. So I really don't need the curly braces because that would represent more like a valley parameter. So it's literally the word details that I expect after the ID. So for this one, we're still only taking one parameter. I've given it a different name of course, because we can't have a clash says Get me could be tails. And then this one has that full query with that includes parameter involved in the operation. So when this vehicle gets returned, gets returned with all of the included details. So let us state that for a test. So from our list of vehicles, I'm going to go over to the Vue components. So I've put a break point at the end of the viewer. And if you look at the data that will be returned, it does have those included, the make the model and whatever else may have been specified, right, So that's fine because I am about to view it. So I will want to include all the details from other tables to have it ready for presentation. And if I go to Edit, you see that the teats, the original get. And then this get is only returning the vehicle with the relevant fields, not with anything additional. So make IS null, model is null and anything that would have been included originally is no, no. So I'm going to go ahead and change all of these drop-down lists to something different. So this is now going to be X5 and it's green. And I'm going to click Update. And then when I look I see high-end day X5 and it was successful. So that is the solution to that edit problem. If you had it, if you didn't have it, then fine, you detect it early and you solved it. Excellent work. But doing the ongoing process of developing software, you're going to see these anomalies in some form of tests. And it's always good when you can figure out how to solve them. 32. Add Validation to Forms: Hey guys, welcome back. In this lesson, we're going to be looking at validation. Validation is very important. Or reality at this point is that we don't know what the user's entering. We don't know if they're even entering the data points are we actually think are important. Because for instance, here we are with create new customer. I can enter maybe just one bit of data, nothing else. And then click Create Custom Anna, we get very incomplete data going to the database being displayed to the user. That doesn't make any sense. We need to add validation to make sure that the data meets certain requirements before it can be submitted or before the user can proceed to enter this bad data into our system. Of course, validation with after occur on the creation form as well as on our edit form. Because the same way they can put in incomplete data, they can go to a complete our completed or acquired and remote, remove vital data and then update it. And then we're still in the same situation so that validation has to occur across anything that is collecting data. So for this example, we're going to be using customers. For our Guinea pig. What I've done is I've added two new fields, firstName and lastName. The data class customer, that was all the way down in shared. We phone customer, we added these two fields. And then we went to package manager, had a failed bill, but then I added the migration and then went ahead and update a database and then know we can collect firstName and lastName. And thus the drive the point home about when we make changes to the database, as in this example. And we have to update the interface to reflect that when we have one component content with for data collection, it makes life much easier. So I'm just going to find our customers form components. And then I can just literally add the two fields here. And they will be applicable for both the edit and the Creates. So let me just hurry up and do this. So for awhile not been seen that we could add more data points to the customers like FirstName, LastName if you didn't do it before and you want to do it nausea chance they can go ahead and do the migration stuff added to the interface as you see fit. And I'm just going to modify the index also. So I'm not one to display the tux. I think that all we really need to display is maybe like full name of the customer, right? And then here I can see customer firstName space at saying customer last name. So then we get the full name being printed in one column. All right, Nice and easy. And then you can literally view the view where you go and see the details. So that is the PSICQUIC change. So let me just focus on this lesson which is validation when we're filling out this form. And you notice that when we're creating the form, we can now put in some stuff that I lose the validation, but it's not working. So we need to let the form law, what rules it should live by. In order to perform this validation, I see this keyword data on notations. Alright, so data annotations are our way to specify rules for the different fields. All right, so what we're putting in a new customer, we need to put in firstName and lastName. We need to put in a tax ID number. We have to have an e-mail address and a legitimate e-mail address that the contact number must be in, but maybe that dress is optional. So let's work with that. Different situations require different rules, but once again, this is our experiment for it today. So I go to the data, talk to us from which this form is derived radicals, we know that it's using customer object, which is of type customers. So the data class is defining the fields that can be collected. So to add data annotations above of field, I will just open square brackets and then start typing. And there are certain keywords, it's not, they'll start typing. So if I want to make something required, I, type II and required, but then after this annotations library, and once that is added, you see Nalgene. So any field that I'm seeing is mandatory can get that required TOD above it. Alright, that required data annotation. So address, I said it's not mandatory. So I'm going to just put a space there so you see that address those or have that required flag above it. So firstName is definitely required. Another thing that's I could say about the first theme is that the string length should be maximum, maybe 100, right? And maybe minimum. So I can just say mini mom, length is equal to minimum length while FirstName that's put into three, you know, it could be jewel or let's put it to two. All right. J. Oh, that's the minimum length similarity for the last name. Minimum length of two, right? You may not necessarily memorize all of these annotations. There are times when I have to actually go and look what they are. But the point is that they are there. And this is the easiest way to specify the rules that govern each field. And another thing about it is that sometimes these annotations actually affect the database. So if I did this before the migration, then it would actually make some demands of hold the deeds of these tables should be designed or generated based on I'm sorry, hold these fields in the database tables should be generated and what constraints our own them. But let's just focus on client-side validation or no toxicity. Leave that alone. But then again, I could say a minimum length, maximum length of maybe 10, and minimum length of maybe eight, right? Depending on the tux IDs that were supporting. All right. Another thing that you'd probably want to do is with a contact number, you can say something like data type. Dot four numbers, so datatype and then I'm specifying that this data type is of type phone number. All right, those are the two things that inform level the fields like for email address, I'm just going to copy and paste up, but there is a datatype that says email address. So then it will try to validate these on general Rosie can get more specific and write your own annotations and validations and attributes. But I'm not going to go into that deeply into it. And right, no, This looks good enough. Let's do a migration and see what comes up. So added validations, so close donors. Let's see. So in this migration file gets generated, you'll see that a bunch of alter column commons of Gamal gray and each one is seeing, okay, and the type is int varchar 15, the maximum lent is 15, phototoxicity. All right, So the validation attributes on the Data class itself will affect the migration, right? This might not necessarily be what you want. It's time for that reason. When you get to bigger applications, you're starting both abstracting and creating layers. So you have the data class and then you have another layer for the applications to obstruct the data classes for this application purposes. And that's usually where you put your validations because you may not necessarily want to see invalidations between the database and the client side. However, in this situation, since we're just using this shared domain classes, and it's really not that harmful considering that if I'm going to screen it's at the interface level, I probably want the database to reject it if it got it anyway, right? So that is what we get when we do a migration on a table that has R on a cross, sorry, that has these data annotations and validation rules. Now I can go ahead and update database because it won't do any harm. But the real test for this lesson is what happens on the interface. Here I'm getting some arrows. These arrows are because it says it cannot insert the value null into a column Touch ID, right? Because here I said tax ID is required as a result, it's modifying it and seeing it is not nullable, send a database NOT null would be, sorry, null, nullable would be on ticked. So I can't pass in null. But I did earlier remove some data from the docs id column. So that's why that migration feel I'm just explaining it to you. All right. Anyhow, let us fix it on the interface level and then we can come back to that migration later on. Alright, so our number one with a towel that are validations are working though this is not exactly how I wanted to demo it. But see you are getting an error here. So we're getting an unhandled error when we're trends and load the costumers, notice that we started off looking into customers, so it was working. But when we go to the console of our browser, we see here where we're getting our 500 response. So thus the spear, any heartache? What's really happening here is that we have the invalid data. The database is querying the invalid Beta. And then all of that error, error, a full data, is trickling all the way up to our interface. The API is Tolkien because the database doesn't know what to do because it sees a bunch of rules and it's getting invalid data, right? So what I'm going to do is clean out the invalid data, meaning the records that I removed the vital data from. So I'm just going to jump over to the object explorer. And what I'm going to do is just remove thing bookings are related, so I have to remove what is the name of our database? There we go. I'll have to remove the bookings as well as the customers, right? So let me just feel data quickly. Okay, I only have one booking anyway. This view data here. And so you see here we have null, null, nothing in the email address and non-linear Touch ID. That's what's causing the issues. So let me just remove these two. In booking. This is for a customer with ID 1. Okay. So I'll remove 23. Those are the tool problem ones. All right. Let's try this. I still got the aerosol attached to do forgettable first name and last name. So I just added test customer. And when we go back, we see that our pH is loading properly. No. So you see the validation. If there's invalid data, then it will not be able to process what it's bringing back. All right, so everything is tightly coupled. So when we create a new user, if I tried to create customer, sorry, creates a new customer and I try to create without putting in anything you see here that we're getting this slew of errors. So this, let me just muck truck to the code and kind of run the parallel with you as to what's happening. Firstly, the data annotations validator is seeing, I am looking at any data valid data annotations attached to the model for which this form is generated. All right, we already went through all the annotations are, these are annotations. It knows this is required and this is the data quality expected and such. So that validator that is at the top of our farm, you seeing, I am watching the field, the value and what the requirements are based on the data, on notations when you hit Submit. All right. You're trying to say send the form to the database. We do only cater for unvalid submit, which means that the invalid submit is odd modes automatic. We can put in an invalid submit, but we're not going that far. The point is though, on submission, it's not going to say, well, this is the validation summary. If the page reloads, then the summary is going to show the only way the page wouldn't reload is if everything was valid and it could proceed. So when the page reloads it showing that validation summary. And then we have that validation methods specific to the field showing up under each one, right? So then we get this under each field, which that message can actually be customized. Because in the required we could put message is 0, error message. There we go. And we could see something like and TR, tux. I D, alright, so that's it. So we can put it in like a custom message instead of that default one to see the field is required. You can put in that error message based on the requirement. And then basically for each one of these, you can specify the error message that you want, right? So you could see name, our stocks ID, so tucks ID does not meet length requirements. All right, So with those two messages, I'm going to refresh and I'm going to just pay attention to the tax ID field. All right, so I reloaded the page. I tried again and notice enterotoxin, that's what's showing up. So our custom message is coming up because it's required and nothing is provided. And if I put one in there, remember that we said it has to be minimum walk it to whatever the land the land was, but look at it. No, touch ID does not meet length requirements. So the message with almost look contextually based on what rule is being violated at that point in time. Currently, if it's required and nothing is there, then I don't need to mention length requirements and looking at the change automatically. So if I start filling this olds and I call this one Archibald, and then look at that. Douglas. All right. All right. And we fill the tote. Cool. If I say create customer, look at that, but then the email address still is not quite meeting our requirements. If I go to Edit, then we need to make sure that proper validation on our EMEA that drink. So for that we actually need this annotation that says email address. So yes, we can see datatype. I think this is more for informational purposes, right? But then at this point we're seeing valid bits and e-mail address. And I think for phone number, we could also see phone. There we go. So you have different validations for different data types. I probably won't be so strict on the phone number though, because I'm not sure what rules the validation is playing by a, but we definitely wanted to be strict on the e-mail address. So let's try that one again. So I'm Buck in the edit view for this customer, if I tried to update, notice it's not going to reject that email address, not a valid email address after make sure I put in something that looks like a typical e-mail address. And then it's satisfied, I click Update and we're good to go. Alright, now that we have valid data in these fields on, in our database, let me try and run this migration again. So the migration is, are there on, I just need to see it update database. And there we go, it's done. So now all we have the new fields and the new constraints are owned all of these fields, right? So at the, at the database level, if you're, if you know about database design and development constraints are rules governing walk can be stored. So this is how you can specify using the code. First approach, the rules around what can be stored in all hall. It when we say n varchar and the size, this is how you can determine the size. But then of course, some of these things are more client side than they are database side. Alright? So from a, from a shared perspective, this is good because we get to specify hold the client should behave and hold the database should behave. But once again, there are times when the rules may not necessarily go both ways at that point, you want to introduce another level of obstruction or wherever view models that govern what the client side or the UI does separate from the database and what the domain objects do. So now that you have a grasp of hole to put validation on your forearms, you know the usual challenge, go ahead and add similar validations to the other tables as you see fit. So i'm I'm not necessarily going to review this one with you because this one is more contexts. You may need validations that I don't necessarily see as important and vice versa. So you go ahead and look at your data requirements. You have business requirements, whatever it is, you know, however you want your data to look and add your validations accordingly. 33. Blazor Display Data - Details: Hey guys, welcome back. In this lesson, we want to set up a component that allows us to view the details of a particular record context. Here's our customer. Now we know that when we created the customer, we entered more than just 1234 bits of data. We also enter tax ID and address. And well, I think that's the point. The point is that we want to be able to view and that's why we have this blue button here that's would be for viewing. So we need to set that component. Now, there are two ways to think about this. One, it needs to be read-only because we don't want to go on the View button and then have to do. We don't want it to be editable because we're viewing the details. That's one too. How exactly do we lay told? A common way to lay it out in a nice detail. Our field to the left, detail to the right kind of format. Some people really just reuse the same farm Leo that was used in the create and edit and display them, but in a read-only fashion. So I think we're going to use that one because that one is really easy to implement. You can always change up your design. Hello you wish, but I'm going to show you some more tricks and things that we can do to extend or form component relative to the different purposes already have the form components creating, we have it editing now we are going to use it to just do view are read on. So using the customer section as the example, we're going to go ahead and add a new component. You can call it view or details alcohol in details. And what I do think we use the word view. We did our head, so let me remove details and do that again. Let me create a new component and I'm going to call it view in keeping with the naming convention that we started off with. So our component is called view. On our component, we're going to have to do something similar to the edit. So we're definitely going to need all of these at the top because we need to navigate to the page, but this one is going to be View. And then we're going to have to have our HTTP client as well as our navigation. Well, we probably don't necessarily need the navigation manager, but we'll see what does do we do. We also need to make sure that we load up our pits. So let me just copy all of this actually put on our view because we are going to be reusing that component. Alright? No, I'm retaining all of this because the parameters coming in, which customer do I want to view? We accept the ID and then we go and fetch the customer. I don't need this edit though, cause editing will happen on this component. Let us focus on this form components section one, I don't need a button takes because I really don't want a button to display anyways, I don't need to set that. I don't need to sit on valid submit because there is no submission that will happen. But one thing I would love to do is tell the form component that when it's loading from this page it should be disabled. So I'm going to add a new parameter. I'm going to call it the sable. And that's going to have a Boolean. It's either true or false. It's either going to be disabled or not. All right. Notice it's blue because we haven't modified form component to recognize. So let's go over to form component and make our modification. So we need that new parameter called disabled. Well I call it the disabled, so that means current not here. So I'm going to call it disabled. Where am I? There we go. And it's going to have a default value of false. All right, so that means if it's not specified, just like with our button takes, if it's not specified, then assume that the farm is not disabled. Alright, quickly, we can easily see if and then our AdSense, sorry. And then IF. And then inside here we can see if it is disabled or if it is not disabled. So that means if disabled is false, then display the button. Alright, so only display this button that says Update are saved when disabled is false. All right, now, as it relates to the form and disabling the farm, and nice easy way to disable a bunch of fields. Enough form would be to wrap them all in a field set and then set the field set to be disabled. So let's do that. So I'm going to add just collapse all of them to make it easier so we can see exactly where everything starts and finishes. And then I'm going to create this tag called Fields sit open and close it. But then I'm going to specify that disabled is equal to and this would be true or false. So if I said true, then this fetus, if it feels set, sorry, is disabled. If I say falls, then nothing would have changed. However, I don't know if it's true or Fazio anyway, I know is what comes in through the parameter. So I'm going to see disabled is going to take the same value that this parameter has. And then I can put all of this inside of this field set. The button is being displayed when disabled is equal to false, so C, and this is the CML seeing equivalent of false. Just to explain case you're a beginner and that's the button. And then we still have the bacillus because when we view we still want option to go back to list. All right, so that's pretty much what we're doing here. So let us backtrack and go back to View. And then you see, you know, it to recognize is that the disabled will be true on the other components that use that form component. We don't have to specify anything with disabled because we set it as default to false. So let's take this for a spin. All right, so when I go and click view, look at what happens. All the data's there. For read-only icon type. All of these are disabled. There's no button here to suggest save our creates. And I can only go back to List. And there we go. So now I can view America. It's nice and easy. And it didn't take much effort. Once again, all we did was to extend our form components to take another parameter in the form of disabled, which is a boolean that we defaulted to false. And then we put this if statement or on the display of the button. If disable this falls, then display the button. And we already have the ductility. So we didn't put that in the statement, of course. And the next thing that we did was on the view component, we go ahead and fetch our record. Basically when the company gets the ID. And then we load up our form component with that customer data and disable it along the way. All right, so that's really it. So you can go ahead and apply that same pattern to the other components of view components that you have. 34. Code Clean Up and Add Changes to GitHub: All right guys, so in this lesson we're just going to review what we've done for this entire section and check our changes into GitHub, commit them. So does my way off recap, what we did was Explorer, how we communicate with the rest API from blazer. So most of our components would have this HTTP client injected in and then code to follow up where we made that call. We also looked at how we can meet the endpoints easier to use across the different components and reduce the risk of error. And we looked at creating reusable components, namely in the form of this form component, where we use it for both our create edit and then we saw how we could extend it to also use for read-only scenarios. We also have introduced some other components like this heading components. So we didn't go through this one together. I introduced it, just know where I use Bootstrap, jumbotron style. Alright? And in, injecting this borrower are sorry, I'm waiting on a parameter called text, which I'm just going to display. So this comes in handy like on our index page where we had to be trans or remember all we wanted to age three with this grass every time. So we can replace those headings with this heading component and we just pass in the text that we want displayed. So reusable components, right? Well so does set up the crowd for all of our resources. So all of our resources can now create, update, delete, and just view the data that's there. In our API. We write it up past wrong where we took off the api slash off the path, whereas that was causing a conflict in the routing. So at the Poupon api slash. And just to show you once again what we did with our endpoints file, we just created a static class with static strings that just built up the different endpoints per resource. So if you get another resource that you need in the API, you can just make her for Institute here and reuse it accordingly anywhere else and application. We also looked at data validation and hole. Adding data annotations to our domain classes will not only affect told the UA deals with validation at the farm level. Also how the database, these constraints when it's creating intermediate, creating the tables are modifying them at the database level. So we see, once again, we discussed that there are times when you may want to separate these two but for no, like Oh, we're just learning won't go that far ahead. I will just mean t in that. So let us just go ahead and go over to get changes. And that is my quick message. And then I'll just go ahead and commit all. And once that is done, you can take a break and I'll see you again in the next lesson. 35. Using a Code-Behind Approach to Blazor Components: Hey guys, In this lesson we're going to be talking about Bowl totally can separate our u coder or markup quote from our logic or the C-Sharp code? No. The fact of the matter is that what we have so far works, right? We have some C sharp mark-up up top. These are more like directives. This is a page. Even these things and authorize, these are all directives. At the top, we have our markup, which is a hybrid of Ariza syntax on HTML syntax. And then we have our code or logic section down below. No, everything works as it is. But then there is an approach that we can take where we actually have two separate files. One for just the markup as we see here. And then we can migrate our certain parts of our logic and C-Sharp code into our code behind file. All right, so I'm going to start off using the colors index.js or component. I think this is nice and simple enough for us to get up and running and get the concept under our fingers before we go ahead and do the rest of our components, if you so desire, it goes, this is completely optional. There's nothing saying that you must do it or if you're not doing it, you're not doing something properly. It depends on your objectives, it depends on your context, of course, but at least you know how to do it should the need arise. So what we're going to do is add a new class to the same folder with our components. And we're actually going to give this class the same name. So it's index.js, razor bullets and extra extension dot CSS. So it's the component name dots raise or dot cs. All right, We'll go ahead and click Add. And what you might notice in the solution explorer is that your index file might get nested under the index razor component. It happens sometimes it doesn't, sometimes it's not happening for me. It might've been for you, but that's no problem. As long as you see the file appear and you've done the name incorrectly, then it should work. So then open up that class file and a we have public partials. So partial means that this is a half implementation are part of implementation of another class, right? So there is a component is a class and we're seeing, well, the C-Sharp class that we're doing is a partial of that. So they all will work together. They will just automatically tied to give them no, that's okay. These two kind of belong to each other, right? So that's all starts off by migrating some afford directives, null. We had injections, someone to take those injections, all of our component. And I'm going to place them inside of the class right. Now instead of having the outside inject, what we'll have is open square brace, capita I inject close square brace. And we'll have to include some libraries, namely the dotnet core components that I vary their goal. And then in other libraries for these, for the clients and these other libraries that we need. So we go ahead and inject and do the same for the JS Runtime. Then we can set this as Get and sit on these two properties. All right. You can put the injectable so they wanted beside it, Sorry, wanted to above it. It doesn't really matter. Has Ozzie, you have the right syntax and you're good to go. Now after doing that, the next thing I want to move over is all of the logic, right? So I'm going to have to take all of this and I'm going to cut it. It is a migration after all. Now the thing is if you double up the code and you'll get a lot of Arezzo boats. It already exists. So let me, let me just show you an example. So if I leave the code here, I copied it and I paste it over here, then you're going to start seeing errors. Well, actually, if I didn't move the directives, so if I injected it here, as well as injected it in the code behind and you will start seeing things about the already exists. Or you have a double initialization of something, which is not a very bad errata on here as an example, ambiguity between this, this property, right? It's easy it here, and it's also sees it there. So once you have seen that kind of error, if you copy and paste that and you know, it's working. So since I've made that point, let me just remove that once more and then move forward. I see half of those areas of disappeared, the missing libraries for our or bits of code. And after doing all of this, where error-free on both sides, if I do a build, alright, so our build was successful and now let's just take it for a spin and make sure it works. But before I do that, what I'm going to do is introduce just a quick console dot write line right here and the uninitialized async, which is just going to say heating code behind. So this is, this will allow us from the console in the browser itself to see this message. And then we will know that It's definitely hitting the code behind not merit component as no code and no injections. All right, so let's just go ahead and take that for us. All right, so here we hit our colors page and everything is clone buck as normal. Let me just go to the inspect element on the console and you'll see here the console.log line that we put in hitting code behind your head. So if at any point you want to print something out to the console or you know, something is going wrong. I want to know if you'd seats in the corner or whatever. You can always use that console.log that line and it will actually just write to the console in the browser. All right, so I can just remove that line. And there you go. That's really all there is to moving your code to a code behind file. Once again, this is actually very optional. You don't have to do this. There is no stipulation that you must do this. As you've seen, we've gotten everything working up until this point. So you can go ahead and do that for the rest of the components. You know, a challenge itself migrates over the code, but of course I'll do it. And later on you'll have my code to compare with just in case you run into any difficulty. 36. Global Error Handling: Hey guys, welcome back. So in this lesson we're going to talk about global error handling. No error handling in c-sharp is really done through what we'll call a try-catch statements. So I just typed tray, press Tab twice and then we got this block of code, right? Try, do something, catch any error that comes your way. Throw means crash the program. So just think about it if you're not so familiar with what error handling is, outside of what I just showed you, just think about every time you use an application when something goes wrong, it has some arrow. It does one of two things. It's either this brings up an error message that says, hey, you know what you tried to do, it didn't quite work. These dragon, the program is still running. Or sometimes it actually just throws the old sort of program, Hey, want to doodle is invalid and then the program crashes and subs working. So that is essentially the error handling. So you can either crash the program through the throw statement that I just want to straighten. Or you can carry out some action. Show a message, let the user know, hey, you know, something went wrong, please try again and then they can try again. We would have seen that in the past when we were we made some modifications and I think we're trying to get my bookings nor the list of bookings. You would've seen that yellow bar come up and go into the console and read through the error and then trendy Bogan, trend fix on phenol, what was wrong? Obviously, you wouldn't necessarily want that kind of user experience for your ear, actual user, it's okay for you as the developer because you need to fix it. But when the user is using the program, you don't want them to see reload and our yellow by something went wrong. I is just a V arrow. What we'll want to do in this lesson is setup. A way that we can actually handle errors no matter where they happen in our application while writing as little code as possible. That's also key. Of course, ticketing contexts because, you know, quote, is not necessarily bad, but you don't want to have to be writing these try-catch blocks every time you're going to carry out an operation that has that API call. Because if the API feels, then our application will feel as we've seen. But then we would have to write this try catch in every single place that we would have been making an API call. And as you can see, I spit all It's the logic and the razor component phys and that would be quite a few. All right. So you probably don't necessarily want to take that approach. It would work, but we're going to try it a different way. So what we're going to be doing to implement our global error handling is installing this package called HTTP client interceptor. So we're just going to go over to new get in our client application. And we're searching for HTTP client interceptor. So we go ahead and install toolbelt, dot blazer, dot interceptor. Now after that has been installed, we're going to go over to our program.cs file, and then we're going to make a few adjustments, starting with our building services that add HTTP client. So I'm going to change this client here. When to open and close parentheses, and I'm just going to put for short SP. And well, we can pull out the word client. So because there are deaf kinds working. So SVN client. And then I'm going to open a curly brace open and close, but I'm going to open it first. And then after the client base address definition, I'm going to close that curly brace. All right? Or if with me here, and then after this we put a semicolon and then we bring 29 again. There we go. So we have, instead of just client will open and close parentheses holding Sb, which represents the service provider, right? And then the plants which represents the HTTP client. And then we open the curly brace and then we define what the base address is for the client. We don't change that line, don't see we do is add a semicolon. Then we close the curly brace and close that parentheses are. We don't modify this either, but inside of these curly braces, I'm going to also the client dots and nibble intercept. All right, and then this is going to need me to include that library toolbelt. What was it toolbelt, Dr. Blaser, extensions, dependency injection. There we go. And then inside of that, we're going to put all a service provider, which is speed or service provider object, which we defined there. All right, then we can set the semicolon there. And then after that we're going to Dawn little bit more, just a bullet here. This is good. We can register our in our intercept services. So are going to say builder dots services. Dots add HTTP client interceptor. So the purpose of the interceptor is to sit bone and monitor all the API calls and it will know whether it was a successful response are not before it comes back. So we've already kind of gone through what, what we've already kind of gone through what success looks like and what an unsuccessful call it looks like in terms of the return codes, right? It's, you know that 500, 400, those are not successful. 200 is generally successful, one hundred and three hundred, those mean some amount of success or the success hasn't been reached dread. So what happens is that when you get to 500 and something went wrong, the application itself, as we've seen, just use a very vague, it doesn't tell you what exactly went wrong. Art doesn't let the user know, hey, you know, technical difficulties drag in later. That's what we're trying to accomplish here. But the interceptor will be a nice. Clean way of having that code being monitored all over without us having to write try catches everywhere. So after this, we have to create a code file to let the interceptor know how it should behave, under what circumstances. So instead of the client project, I'm gonna assume that creates a new folder. I'm just going to call it its services. And then in services we're adding a new class. And I'm going to call it http interceptor service. It UDP intercept of service. And we go ahead and add that. And we're going to start off with a constructor. So we need to inject two things to be very specific. We need the http interceptor and we need our nav, Monica. So we can just go ahead and put those into the parameters for our constructor. Go ahead and include any missing references. Now we get into a cool little thing here to get them actually initialized in the cold results, you know, money while you're writing it or we have been doing Windows, click the light bulb and then we say create and assign field. So it will just automatically go ahead and create an assigned the field and do that whole in ejection. So we can do that for both parameters, for both the manager and the interceptor. And notice I'm using field not property because it's private greed, or the right. By default, it doesn't come with the underscore. So I'm just going to put onto scores to be consistent with the naming convention I've been using up until this point. But that's not much of a big deal. Outside of the Smith. You just use this because they have the same names. So that's fine. We can move ahead, know that we have done our injections. And the first thing that we're going to do is setup something like an event handler in on this one. This is called a wanted to continuously make another call to something. So it's like an event, right? So I'm going to say public void, Let's say monitor event, right? And I'm just going to do that 19 initialization and see interceptor dot. And then you see here are our events that we can set up bread. So I'm going to say after send and then do it's like an increment. So after cin, meaning continuously every time you're doing this, just make this function call. So I'm going to see inter response. Once again, we want this, this is going to sit in between our client and the API call. So it needs to actually watch when a call is made, get Butler's ones before the client and then wearable to tell you what it should do when it intercepts the response. All right, So on intercepting our response, what lawn to do is evaluate what kind of response it is and take an action. So I'm just generate the method for intercept response, private void, intercept response and the sender and the event arguments. If you've ever worked with WinForms or web forms, you would know all about these if you've never had to build them outside of that context, of course, but let us continue. So what we want to do is message. We can just meet that an empty string to begin with. And then I wanted to see if E, So E represents the event or the response from the event, the outcome of me trying to do something. So E dot. And if you look here, you'll see that you have access to the response under requests. I can watch to see what was requested and the watch to see what responses. So I'm going to say if E dot response dot is success code, all right, is success quote means it's the 200 to 300, the 100 and something that doesn't mean an error, right? Well, if you look at it by definition, it's really to 100 to 99, otherwise it's false. So that's what success is. So I really wanted to do error handling, which means that if I want, I want to really watch, if it's not a success code, then I do something. All right, because then if it is a salt Cisco, then application can run as normal. But if it wasn't a successful than I wanted to spring into action. So I wanted to say var response code is equal to. And then we can just say e dot dot Stato scored. There we go. And then we can have like a switch our if statement just to go through the different options. So what if I wanted to do something if it was a 40 for different from if it was a 500 different from if it was a 40, 1, which means unauthorized and stuff like that. Right. So you have different if you want to meet different different paths based on, oh my god, who got that? That was an accident on my empire. But there it's already giving you all of the status codes which will probably really don't even need, we don't need all of these. So I'm just going to undo that. And the ones that were really, really, really want to focus on anyway would be case HTTP status code. Let me just do this off HTTP status code and do any includes that I need to do. And then I want to maybe watch for 500 or well, let's start off with the not found, right? So if it's on not phoned, then I want to take some course of action. Let me just put that there. And let's say if it was maybe 40 Huan are an unauthorized, unauthorized and they also have forbidden, right? So if it's either one of these, then we probably wanted to show the same again, a message and then the defaults, I'll just leave that to say that if it wasn't any of these, then just default. So that generic error message beach that says, you know, something went wrong these dragon later, which would probably be like a 500. So I'm just showing you you can get specific. Or you can just have that generic. So even if we didn't want to see different paths, we could just say, if it was not a success message, our success scored, then do this. Alright, so I'm going to put these buck. And the reason we have the navigation manager, the manager injected is that I want us to have different pages for the different paths that could be taken. All right. So so just went ahead and filled all the rest of it and I'll just walk you through soil. The case for the not phoned. We're going to say a novel manager dot navigate to a page called fluorophore, which of course we are going to create. This message is what will get displayed probably in the, the console of the browser. So we're going to have to throw something off to all of this, but we'll get there eventually. So we go ahead and navigate to the 40 for we loved this to the console. If you're far mid-March, unauthorized will navigate to unauthorized. We also loved this in the console and then default, meaning anything else that was a failure. We just navigate to the 50, 100 page and then we see something went wrong. Please contact administrator. After doing all those checks, we're going to have to throw an exception. So we can just say throw new exception and we're just going to pass in that message. All right, so that will kinda trigger the obligation to know that, hey, something actually went wrong. But once again, we can actually navigate to a page where we show the user a nice, friendly we, that we handled the situation. Now after doing all of that, we have one more thing we need to do where we need to dispose off the event. So we started the event where we're continuously calling this method to watch. And then we need to call dispose event, where we're going to do the opposite. So here we were adding and accumulating. Here we just do minus equals art. So after doing all of that, we are going to have to register and our program.cs, the facts that this service exists. So we'll do that underneath. The ad is HTTP client interceptor where we just put in and sculpt and put in the name of the file, of course, include any missing references. And then we're ready to go ahead and implement this whole service. So let us go back to our index dot dot CSS file. And what we'll do is let this partial class inherit from I disposable. So this will actually give us a method that allows us to dispose of any object not we don't want after its lifetime has gone. So usually what happens is that the dispose is called when the component goes on are when the component is no longer needed by the application. But what we want to do is put in some custom logic to dispose off our interceptor. So, well, before we can do that, Let's inject the interceptor. So I'm just going to duplicate that line and I'm going to add HTTP inter scepter. Let me just copy this interceptor service. Instead of trends are isotopes. Go ahead, include missing references. Alright, and then let me start off with the dispose. That's probably the easiest one to do here. We just say interceptor dot and we already have the method that says dispose event. So we can just go ahead and do that, right? No, outside of that, we want to actually monitor what's going to happen. So right before we actually make our call, we can see interceptor dot monitor events. And that's it. So when we say monetary event, it's going to then start this method which is no monitoring to see what is the response and what should it do afterwards. All right, so that is a nice, clean way of having something there to watch what is going to happen. So we can just do that everywhere. We have a service called a boat to be made in as many files. I see that this is much easier to put in. Then the whole try-catch, try-catch, try-catch, because that would lead to a lot of repetition. So I'm going to do that again in the create. So I actually inadvertently put the code there without any injections and it's from scratch again one I'm going to put in the eye disposable implements that interface. And then I'm going to see, and you don't want to necessarily after write the code in this artery and I'm sure you know that, but I know that you can write it in any order if you're comfortable with as long as you follow the steps. So we have the interceptor being disposed, we have the intercept are monitoring the function, sorry, the API call here. And then the last part of this puzzle is just the injected. And I'm just going to ones again, copy this line so I don't have to write it all up from scratch and voila. All right, so we're bearing note on completing this activity. Another thing that we need to do is to create the error pages because we did see that wanted a page called fluorophore to be navigated tool, one called on author as unwanted called 500s. So I just went dead and created those components. 40 for and it's nothing funds. He's just a page with an H1 tag. Seeing takes us danger resource you're looking for, it could not be found. It's navigational address as an OLAP to say page slash the address. So that's 404. We have a similar setup for the 500 and we have unauthorized and bear in mind on Azar as your components have to start with capital letters or unauthorized is capital U, but the navigational address is fine as a common little. That's up to you. I'm not putting anything too fancy in these components, but of course you can enhance them as you or your context requires. No, in the colors controller, I'm going to put a not found right at the start of this method where we, you know, when the index page is called a cause get colors, right? So what it calls the get and tries to get the colors. So we're just going to return our 40 for upfront and see how this reacts. Right? So let us go ahead and look at the page for colors and we're heating the breakpoints so we see, you know, that it should just return a 400 for someone to remove the breakpoints and press F5 for it to continue. And voila, the resource you're looking for could not be phone. That is our 404 page. All right. Of course we're getting this unhandled error because we throw an exception. If we look in the console, we're going to see that exception being thrown with the message, right? So it's up to you if you really want to throw an exception and you know how this yellow bar loading, because that doesn't mean anything to the user, right? Not that we're using. Also go into the console and look at the arrows. So we could actually do without this, throw new exception cards at the end of the interceptor. And the interceptor really does handles everything gracefully for us. All right, so we could just say, navigate to this page, right? We could even enhance the, the components such that we just pass in the message as parameter. So we don't want tough to write told that takes money. Well, it's, once again, it's entirely up to you, but you have the concept and also you can go ahead and implement this in your application. And it is a nice, clean way to handle arrows because we don't know what might happen with the API. Something might get interrupted in our quality get bokeh 500. Instead of writing too much custom code for every potential 500, we just write generic code, global code to see something went wrong. Please drag in our p's gunshot administrators though. It's entirely up to you. 37. Add Changes to GitHub: Hey guys, welcome back. So we've gotten to the end of another checkpoint. And in this section, all we really did was look at how we can refactor some of the code in our components by having our or UI components section on different from the code behind, right. So I did that for colors, customers, mixed models, vehicles. I didn't do it for bookings. So I left this one in its original state to preserve what it can look like. And then I did it for all the others, right? Also didn't do it for the foreign components because really that was all there was to it. So I didn't bother to some just showing you that it's not absolutely necessary. Of course, it's not necessarily ideal to mix and match it the way that we're seeing me have it in this section, it's like this and then separated in other sections. It's good to be consistent right across the board. However, I leave those there as code examples for your feature or friends. Other than that, we also added global error handling using the HTTP, http interceptor, which allows us to just use one line to kind of monitor. And we did that specifically in the index one line to kind of monitor if it will be successful or not. Of course, with this one line, we have the injector, customer service, as well as make sure that we dispose just to make sure nothing lingers in memory too long. So after making all these changes, we want to go ahead and checked in. So as usual we read or helpful message and then go ahead and commit all and sink. 38. Customize Identity Layout and Logic: Hey guys, welcome back. So what we want to do in this lesson is kind of explore some of the more important parts of the identity library and see what we need to modify. What's a nice to have and just have a general feel of it. So I'm not going to walk through it in great detail, at least not in this course. If you want to understand identity and understand all of the functionality, can shuffle my other course where we go through identity, core and all of the inner workings foreign, although we just want to kind of gloss over it because at the end of the day, we want to provide some basic to protect her up. And we have been doing that. We implemented or a login, we implemented our registration. And in our project we had scuffled bunch of pages related to identity and managements. If we just expand this, if you've forgotten in the server project, in areas identity pages, if you had followed me, then you'd have scaffolded all of these pages. See that? And instead of menorrhagia, more pages so that those positions that they actually provided a lot of, maybe not all off, but quite a few pages geared towards helping you and your users manage own user or cones inside of the application. If you didn't follow the steps, you could always go to Pages, click, Add new scaffold item, then you see identity, and then you can scuffle adults. Otherwise, you can always revisit the previous video. Now in this video, I just want us to kind of walk through what is there and how we can tweak it to maybe have a better experience for ourselves. So we've been doing the login, we know how to seed uses and so on. I see that this page is drastically different from the rest of our website. Now you probably want to modify this. And if you really look at the contents of the page, you'll see that not everything here is really relevant to our application. So you can, if you don't make it look exactly like this skin with the sad part, sidebar and everything. But you probably don't need to include the text using another service to login, which of course is contextual, because if this is an internal up for your company, then the only service you want to facilitate is the company managed user or cones. If it is a public facing application for general users, general public, then you may want to look at extending it to support Facebook login and so on. But once again, I'm not going to cover all of that in this particular course. But if you want to modify this page, you'd see that in the URL it says identity slash a colon slash login. So if we go back to our project and look in our scaffolded pages would see identity are co-owned. And then we have the login page. So this is the page that is being served up to us when we click login. So that means any changes on to me if we want to remove the forgot password link. So it's a we're using recent confirmation link. Or let's start with the external, the external logins. So we don't have any external logins at wanted someone to remove this entire section. I'm just going to collapse that they've deleted. And then probably I want this section on with the text boxes to take up more space. So what I'll do is expand this to MD 12 so it will stretch for ads across. All right, I can also say Use your company cones to login. All right, so these are all things that we can do right here in the application. And you can modify it how you see fit. If you wanted to change the general layout of the page because you'll notice that both the login and the register kind of have a similar layout. Once again, there are just a page is available to us for modification. Here's a register page. So if we wanted to make a similar modification to remove that actionable external logins, I can also collapse and delete that, extend this form to take up the entire page. And then whatever all the changes we need to make, we can make. No, I wasn't on the point that if we wanted to change the general layout of this entire these pages, then what we can do is go over into the solution explorer and look and view starts, which will indicate where that layout page is phoned. And that is pages slash shared slash layout.css HTML. And if you look in shared, you won't see it. But then if you go down to the Pages folder, then you'll find shared. And there is our layout. So from here, and if you've ever used the dotnet Core MVC or easel pages, you will be at least familiar with this kind of layout page where it's standard Bootstrap 4 page. And then you can change the menu items. So you can see here current management application, instead of just the project name, you know, you can customize all of these things. It's showing a bunch of partials and some conditions. You probably don't necessarily want to modify every single thing, but you can certainly change a few things to make it feel more like your application as opposed to just a mother template. All right, so car and Tom management application, you put the key places. If there's a privacy statement, then sure, you go ahead and do that. And it renders the year and all of these wonderful things I know most of this once again, was kind of done for the support of the identity server related pages. All right, so you want to be very careful how you make modifications. But for general HTML tags, anything that's not to raise oriented, then you can go ahead and make your changes and fix them as you see fit. Now I'm just going to restart this application given all of the changes that I just made. And then when the application comes up and I go to login, know you're going to see the login page looks differently, right? I just modified the layout to some extent. The farm is no longer asking Theobald, it's anything that's not relevant to the application. And the text looks a bit more inviting null. All right. And just the same for the registration page? No, in terms of adding more fields to the registration page. And another common thing that you probably want to do is not only asked for the e-mail, but maybe e-mail or username or just username because Ryan No, what happens is that this form is defaulting to asking for an email address for the username and just close some tabs that are not absolutely irrelevant, right? No. All right. So let's start off with the register page. All right. So the register page is being Razor pages application are arrays of pages page. So it has the code behind, right? So if we just look back pages by repeated, you'll see the CSS, HTML. Css. We kind of looked at something like that when already can't are blazer components and the code behind file, right? So ever page here has a code behind. So whatever register dot CSS, HTML and CSS file behind it, this is the CS5 behind it. And what you'll see here is that it has a key property called input model of type input model called input. And then that is really just a class. And this glass is used to model the form. So this class only has field for email address, which is being strongly typed as an e-mail address. We looked at validation earlier. So that's why we have to use an e-mail address at the time of registering and then subsequently we have to use it for login purposes. Know that if we remove this constraint and we said, you know, public string, username for argument's sake. And we said enter your username or your email address. It's not as strict as to require an e-mail address at that point. However, I won't trouble that. I think I'd e-mail address is a good enough way to keep everything you need for the username column. And it serves a purpose of going in both username and email address. So we can leave that foreign on disappointing all these key things in case you want to probably modified. Know our application user. Let me just stop and jump over to our application user model. Here we see that we have FirstName, LastName, and then it's, it's inheriting from identity user. So that means we have the capacity to store first name and last name in our database for every user, which is not a bad option, right? No. What if we want it when the person is registering the enter first name and last name. And by extension, you can add other fields if you want a date of birth, gender, et cetera, you could add all of that here. But then the key part to it is that in the input model, you need to have representatives on for these fields. So if i in the input model put in interests well those two fields, and let's meet them required because it doesn't make sense to us. Or make use an IAM, sorry, firstName and lastName optional, but email is not right. So e-mail, first name, last name, password, and confirm password. And you see that they are using the data on notations that we looked at when already can't validations, right? So all of those things are required no, on get. All of those is low. The pH. We can even remove this particle at external logins. We're not using an external logins. What's I'm not linear code just yet. On post. We see that it validates. So this is what we validate. And then it builds the user object before it goes ahead and creates it. No, I just asked for firstName and lastName in addition to the email and password. So that means in building this object, I can know provide values for firstName. And now those Brian Kernighan, firstname can now be equal to input dot first name. Once again, input is just the object type that represents input model, which is what we just modified. So I can now put in the firstName and I can now put in the last name. So that means when somebody registers, they should have data in the first name and last name fields. Well, that's the code behind the interface, however, still does not reflect that. So what we're going to do is modify the interface to know that it should have text boxes for first name and last name. And now those do that simply by copying and pasting the text box for email. And I'll just say at the top firstName. So that's a label for first named input for first name and a validation for firstName. And then the same for LastName. And then email when I copy them via twice. So Email remains as email. So know that we've changed this form when somebody registers, they will be able to provide their full details and then register and have that record. So let's do that one for a quick test. So I'm just going to register so it sees schema for first name, last name, no noticed FirstName. That's kind of it together. It's camelCase but there is no space in between, so I'm just going to fix that before I even go any further. So back in input, what I can do is say display. My name is first the name with a space in it. All right, so that's what the label will render. All right, so this won't be the last names, so let me just restart that and show you what that looks like. And here we are. Firstname, lastname, so they see that looks much better. So let me just put in some random values and hit Register and let's see what happens. All right, so the register, some process was successful and that's because it successfully on post created that object, created the user. Went ahead and since that code now this part of Etruria, that email sender and so on. We can look at it later. Hold to actually sets up on email system in our blazer application, which is very important for security because we want to verify that the person who is registering can receive and validate Will they are, right. It's just another level of security that brings comfort to both the company and to your potential clients, right? So that's what happened when we register. Alright? Now if you just look at my insufficiency that that could use a little fixing up and that's fine. But then if I click the section that says Hello, GOP's is going to bring up the profile page, which is once again just another file that is found inside this folder. No, This one is inside manage, says a colon slash manage. And I believe that that would be index, right? So a colon slash manage. And then we look for the index file, and this is the page we're looking at where it's showing the username, the full number, anything that is in the system for this person writes could easily put that one in, Save and it would update the profile with that, I click email, it's showing me that you see all of these things are right here. So you can give a user the ability to manage their own or co-owned, reset their password or changes their password or other, and setup to a PHP if needs be. We don't have any tophi it, but I'm just showing you all of what our identity library allows us to do. Once again, you can always modify the layout if you want it to display more information here. So right, no index model is simply displaying phone number. But then you can always extend that. You can always extend it to include the FirstName, LastName, and any other details that you want them to use it to be able to see and modify when the R on that. Now bucking are up, I'm just going to log out. And then you'll see that there's an error logging or no, when we were setting up the navigation or rewriting the whole navigation component, I would have removed some vervet quotes. So I'm going to write that wrong or right? No, no. If we jump over to the nav menu component, you'd see though we had poor to the login display contents to this area. All right, now if I could just compare this section for the authorization on with the login display, you'd see well, firstly, component comparison. There are some injections on some libraries being used in the login display. And there's also code at the end of the login display component. Now what happens is that logo procedure is really like a form submission as opposed to just link click. So I would have replaced the button that would have submitted a form or at least started a form submission process to navigate to the authenticates vote. This part is very vital. I would have bypass that and jumped directly to the URL, which is why we've got that error. It was saying, well, if it's coming from an unknown source. So what I need to do or what we need to do is let this NovaLink onclick called this code. But then once again, this is all in and login display. So just for simplicity sake, we're going to expunge the login display. And we're just going to put all the code in the nav menu scenes. That's where everything is happening with authorized and the many items and everything, right? So I'm just going to copy this function from login display. If you have deleted it, if you have, then that's fine. You can always just pause and reproduce that bit of code. And I'm also going to take these libraries, so injects and also Shan State Manager, navigation manager. And these two libraries, or top or well, the libraries and the injected functions or classes, right? And then what we can do is on the nav link that says F equals authentication and logos. I'm going to put that as a hash touts it as it's seems that gets an active link. But thankfully, we're using a blazer component and blazer components can do on click. So the same way that the button in login display, that was just a button. And it would've done that. Onclick begins psi naught. I'm going to tell this NovaLink that when it is clicked, it should call that function. Begin saying ALT, which is here. Once again, you feel wanted to separate these PFAS have the component and the code behind file. Then we already went through an exercise or we did that. So few free to go ahead and do that. But for this simple operation, I'm just going to keep it simple. I'm not went to do all of that. All right. So let us try this logo process once. So I'm Buck as JPSM management.com, and then I click logout and you see that it's an entirely different process, entirely different feeling. I know that it's actually working. So you see where a lot of dots and you can go back and register. Not. So you see even those procedures can be managed with our pages and how everything flows from the user's perspective across the different parts of the application. Of course, we authorize all of these links. So once you click on a link, you have to be authorized. And the deeper reason for authorization, just as a recap, is that once you authorize you automatic Valley, It's a cookie created which has a Tolkien. And this Tolkien is what is used to authenticate this user across the APA, the server project. Alright, so remember that whatever the user is doing when they're adding cars are doing wonderful operation. They're really in the client by parts. All right? And then when they have to hit one of these API endpoints, there has to be a Tolkien attached to this request. And that is a part of what was sent up here when we built up this HTTP client. And we told it that it should always send an authorization message handler. Now later on we'll look at how we can send on authorized API requests. Because as it stuns, once we're using this client, it is automatically going to try and attach a Tolkien. Say if no token is present, then you will always get backup 40, 1 or 4 or 3, seeing you cannot access the resource on the API side. So that's his way. Having the user login is so vital. But then there might be a situation where you don't want the user or you don't want to force the user to have to login to access a certain page or be able to interact with certain data. There might be that situation. So we will look at how weekend do that later on. 39. JavaScript Interop With Third Party Libraries: Hey guys, welcome back. In this lesson, we want to take a deeper dive into JavaScript, interop, know we touched on It's a bit when we made one call. And that was to our own little internal onclick method. When we click on our button here, we had that confirmation on. Are you sure you want to delete right? Now? The reality is that you probably will want this to look a bit better. You don't want it to be the vanilla alert ton of confirm box that comes built-in with a browser. You probably want to use a third party library like maybe so you to learn so far, so on to kind of give it a bit more character. Another thing that you probably want to do is modify a whole, that data is being displayed. So right, No, everything is just being displayed in arugula table and it's just going on and on and on. So the more guards I was a lamda, the pH is no. Today what we're going to be doing is focusing on the display of the data here in the grid. So we're going to putting in a grid rather grad and I went to focus on the bookings page because I think this one would do well with the grid more than the others, at least within the context, but there's no limitation. Alright? So what we want to do is transform this tabular display of data into a grid. And the grid that we'll be using today is the tables. So if you've never used the two tables before, you can go to Data Tables.net and you can use this exact URL slash, examples slash styling slash Bootstrap 4 dot HTML. So we're using Bootstrap 4 in our blazer application. So I want the skin for data tables that will look best with the overall layout that we have. All right, so when you're on this page, you'll be able to experiment with it. If you're familiar with data tables, anybody know what we're all about today? If not, then it's a nice, fun way, an easy way to kind of tabulate all of the data that's coming in. It has automatic paging. Granted, all of this is happening client-side. So this is like a quick win. Later on as the application begins to grow, you probably want to implement. Paging on the server side will reduce the load. But for null for a small up who just seem to have this quick win by implementing data tables. And it will give us a bit more insight into how blazer interacts with JavaScript and other things that we need to consider when doing this kind of operation. So below the show, all of the access or the CDN links for all of the resources needed for data tables to work. And they should be included in that particular order. Alright, and that minimum, that code is required. After all of this? No. These are links and these are links to files that are hosted on the Internet. They are good in terms of when you have Internet access. They do held application to load faster, especially like overusing the klan said blazer. And especially if somebody decides to go progressive on download the app. You know, not having the physical Fazlollah reduce the footprint of the AP in general. However, in offline mode or somebody tries to open that up and it'll into immediate Internet access. And these links cannot be reached at the time. Then in that situation is probably bits it to have the physical files. So you know, you can give and take and assess your risk appetite. But once again, for the quick win and just for the overall feel of how JS interrupt works, we're just going to be using the CDN links and we'll be including these references in our project as we go along. Now let's get started. And what we're going to do is create some scriptural references to these links inside of our blazer app null, where we have to include them is very specific on particle. So we have to go to the index.html page and I'm just going to stop there running or at all so we can do our editing in the index.html page that's in the root folder, and that's index.html. We'd need to include or scripture references before our blazer dot WebAssembly ab.js file. So I mean, we can include it before the authentication service, but that one is kind of secondary to the fanatic most commonly for this one now this is because we're using the blazer client are WebAssembly project. If we're using the blazer server projects, then it would be in the host file and a similar constraint would actually apply. So let's continue in our index.html and I'll just paste them there. And then what we need to do is kind of her up them inside of scripts dot js. So I'm going to say script is equal to S, Script, SRC is equal to and then the link. And then we just go ahead and close our script tags. And then we're going to do that for all of these links. And once you have completed that and you have your links looking something like this, let me just remove that. Then we can go back over to the data tables page and sorry, and we can fetch the CSS files so anything that you're able to use and it's almost the same rules apply when dealing with gustation or sorry, the CSS is what we want. The same rules apply when dealing with the web applications. If we are going to be using in the library, you have to make sure that you have all the relevant references to the library. So I've gone ahead and added the tool links to the data table CSS file, of course, swell actually only need one because one of them is Bootstrap, which I already have in my project. So I'm actually going to just have one reference That's a screen that's, I'll quickly before we proceed. So when they have the wanderer reference, and that is the second her friends here. The data tables dot Bootstrap, 4 dot main.css. So that's what we need. Know. We need to write our own script file, which we'll actually do some dynamic initialization because if we plan to use the data table in multiple places that we need to be able to call a specific function from the deeds of tables, passing the table that we want it to be applied to. The table name or some identifier for the table, whether it's a class or it's the ID, we know how this thing works, or if you're already familiar with how it works. That's why we need to write this custom JavaScript that we have control over. All right, so I'm just going to in the www root folder, go ahead and add a new folder and I'm going to call it Scripts. And then inside I'll scripts, I'm going to add a new item in the form of a JavaScript file. And I'm just going to call it data table dot js, data table dot js there we will know in data.table ab.js, I'm going to have a function that call me keep it simple. Data table or the table. All right? And this function is going to take Environmental Quality the table. All right? And pretty much all of this is going to do is initialize the documents and we say document.ready. You know that that's a standard part of jQuery. Heard function, open and close brace, open and close curly brace. And then inside of this we're just going to look for elements or dollar sign table. So like I said, the element name or something to identify the element is what will be passed in as a parameter. So table dot and then it's as simple as data.table. So that's whole data tables would require you to initialize it. All right, We're only going through this because we need it to be accessible through the GS interrupt, interrupt. But then otherwise, we all know that that is all we really need in a regular HTML sitting part. The next one that I'm going to do is remove our dispose the the tail because what happens is that when the page moves on, we don't want that component to be lingering in the browser, in the console, and lingering in memory that all I was at data table three-page is our goal we wanted through moved, right? So we're going to call this dispose method that we know that we're going to clear that table off any reference. It's hot, right? We still need the document or any, so I'm just going to copy and paste that. But inside of this section I'm going to say table dot data, table dot destroy. You want or move their friends. And then I'm going to find the elements. And I'll do that by saying document.write, query selector and look for table plus. And then a key word that usually goes on, it's that says underscore wrapper. And then I'll say element parent node removed child elements, right? So I'm just removing all traces of this element once we're finished with the DataTable, So say are on the page, will load the data table, you navigate away. We want to kill the data table and remove the element from the entire window, from the entire application until you come back anyway after reinitialize, it is a subparts of the territory. It's something that needs to be done to keep the obligation on runtime clean and once again, reduce that footprint of the application. All right, so now that we have this script file in the HTML, of course the Ultimaker for institutes, and I'll make reference to it after everything, right? So I can just drag and drop that from the Solution Explorer and there's our custom script file. Now let's head over into the component where we intend to use this JS Runtime. And I did say that we're going to start with the bookings, go over to the index for the bookings. And I'm going to start off by including up top fret on the inject, saying implements disposable. So I disposable is C sharps we off doing garbage collection would have actually interacted with it before. No. So when this component is finished, I disposable comes in and destroys the component in memory garbage collection. So this is going to work hand-in-hand with our dispose method here, but we'll see it in a few seconds. Co-executive, everything will tie it together. Now I'm going to give our table here and IBM when to call it booking team, right? Or bookings tables. This bookings table, right? No, We all know that. By now we should know that in HTML and we give an element an ID, it's a unique identifier. This will come in handy when we're going to call our async method. Because remember that we are going to be calling this add to the data table method, which is going to take as a parameter the name of the element it should apply the data table called 2M. So what we're going to do here is call another protected methods. So protected is sink and we wanted to override the task. And this one that we're overriding is on after render is seeing, which takes a Boolean called first render to use on the loads up in the IntelliSense. Let me try that again. Alright, so protected over it and then space. There we go. Then we get on after under a sings I think because I wrote async earlier, it didn't it didn't prompt that one. All right. Let me just fix that up so I want it to be async. Of course, there we go. So this method, and I'm doing it right onto the uninitialized. So you can see that there are a few methods here that can be overdone for a specific purposes. So the after render, a sink really is a method to see after the component has rendered, what would you have me do? Now remember, I will say that it's important to do certain things at certain points. So the way we included the files, maybe that could've been an exaggeration, maybe we could have mixed on much the order. Of course. It's better to just load them up before everything's split the Maryland here, let me just put them back. All right. That's fine. But then as far as a component is concerned, if we're going to be calling JavaScript functions from our own corridor, from third-party code. We need to do that after the component has loaded all its assets. So that's what this method says on after renderer async, after the component has finished loading of everything that it needs to do. What do you want to do with that extra? So while we want to do it, That's extra. So I'll just remove that default line. And I'll see that I don't want to wait a, G, S, and we know this code, we did this quarter, the right JS invoke is sink and get back a value so much I'm just going to copy this, right? It's the same code. Js is our object, invoke a sink. The only difference is the return type. So I wanted to put this return type as object. Or you can actually see a sink void art, sorry, invoke void async, which doesn't return anything, right? So let's try the void. If the boy doesn't work, we just go back to the, to the invoke Async. But when we do this, we need to pass in that method name. So in the case of our confirm, the method name in JavaScript is confirm, right? In this situation, the name of the method we're calling is our data table. That's our methodology created add data table. Okay, What is the parameters? So this does take a parameter, the confirm, the message that we want it displayed in this situation, our parameter here is the ID value for our table. All right, C hashtag or pound, and then the ID value, and that's it. So when the component has rendered, we want to invoke the JavaScript code. All right? No, I would have mentioned that the disposable, so we need to see what happens when you're disposing. So we're going to tie the jQuery dispose code to the almost default component disposed codes. I'm just going to say void I disposable dot dispose when you are disposing. This is what I want you to do for me. I want to call g is invoke. And I'll just show you this real Is this, right, but different method this time, same parameter, same method of calling except I'm calling data table is disposed and this is a void, so we're not willing to wait that method call. Alright, so let us take this for a spin and see if our booking speech will reflect our needs that no one we go to our bookings page. There we go. We have our data table displaying our paging options. We can search its instantaneous everything that we could do in the regular HTML sitting weekend, no do in our blazer application, this just goes to show how easy it is to incorporate a third party library. So I think I started off with the example that you probably want to change old disconfirm to something like a sweet alert or something that you can go ahead and try it out on your own, get the assets, put them in the appropriate places, and then you just have to call your invoke at the appropriate time. Now notice that when I navigate to the other pages, everything is clean. I haven't put the data tables on the other pages, but when I go back to bookings, everything is fine. Now, if it was not disposing and I'll just show you the consequence of the dispossessing case. You're thinking maybe it's unnecessary steps. So I'm just going to comment that line out restart. And then we looked at the bookings page. Now look at the top. What I did was go to bookings, go to another page on combustible chins. Now I'm on bookings. Look at what happens when I go to vehicles. It's still stocking up, so it's not getting rid of the data table from the container. Because remember that this WebAssembly up once it's loaded, everything is front-loaded at once. So we have to keep us small footprint off certain things that we don't want pervasive across application in this situation, that data table from just the bookings page is going up, started appearing on customers. And every time I go to bookings and go to another page assessment to continue stacking up and stacking up. So that is why that dispose code is of the utmost importance. So Alice Goldbach uncommented to that. I'm sorry. I didn't mean to just experimenting and I'm glad you're here. Alright, so that is a nice and easy introduction to interrupt JavaScript interrupt, Sorry, with blazer. You can extend on into again tra, other third party libraries, and then maybe can push your skills up bids and develop a custom library or component that just implements one of these libraries so that you can reduce the amount of work and you're calling on repeating code for GS invoke. All right. 40. File Upload Support: Hey guys, welcome back. In this lesson we want to take a look at the file upload support that Blaser has. So what we're going to be doing for this lesson is adding an image field to the vehicle table. File uploads are not limited to images of course, but as an example, we'll use the vehicle because when we're adding a new vehicle, probably wanted to take a picture of the vehicle, puts it in the system for whatever reason. But it can also be applied to maybe when we are on-boarding customer, we would probably want some particulars on them. You know, their passports are some valid driver's license are some forms of documentation. So the same concept that we're about to apply it to uploading an image of the vehicle could be applied in multiple scenarios across whatever business rules at requirements you might have. So let's get started. So in the vehicle domain class, we want to add two new fields, and I'm just going to add them below here. And the first one is going to be public by RE, so it's just a budgetary and I'm going to call this image, there's this cloud image, all right? And get set when we are transporting our image from the client application over to the API. We're going to have to kind of convert it into a byte array, a farm, and then we're going to disassemble it, send it over the wire, and then reassemble it to save it on the other side. And that's pretty much what splint off topic. But what we really want to do is take note of the name, someone to have this new field called image name. And this is really what is going to identify the image. So what we're going to do is when we recreate it and save it to the disk on the API said we're going to see whatever name we gave it in the database so that they can be retrieved whenever we need it. No, one of these is required in the database, and this is not the one that's required. So what we can do is add an annotation above it to say and not mopped. All right, so not mopped is basically going to see a when we're about to do a migration, ignored this field. All right, so this is very important anytime you are editing your domain classes and you probably put in fields that you don't want in the database. You just add this annotation not mapped and it will skip the database. All right, so let's see that in practice. So I'm just going to add migration. And this is going to be the image to the cloak. Vehicles. Let that go. And when that is done, we can take a look and we see that we only have one of the two fields that we just added. So image name is no added two vehicles. So we can just go ahead and get the data, right. So know that that is done. Let's jump over to the API and make a few adjustments. First order of business, please inject these two lines or these two libraries. We have the web host and environment, and we have the AI HTTP context accessor. So this is going to give us access to the static files folder. So dotnet core by default as a static files folder, which is our www root of Kind of gone through that earlier. What is stored in that? So inside of that folder, we want to have another folder called Upload. So you can go ahead and create that just right-click, go to add and say new folder and call it uploads. And then our eye web host environment objects that we're injecting here will actually give us easy access to building our route to our uploads folder or HTTP contexts access so as you know, gives us access to some Request details on one-off requests, details that we want is to the current server or the current host value, so that we actually build a URL, which is what we're going to be storing in the database. So lets us jump down to the Creates. All right, and just remove my breakpoint there. And we already know that we're doing our global error handling on this side of the API. So we don't have to worry about trying and catching if there's any error along the way, it will throw the 500 and we can move along. But what we want to accomplish here is the construction of the URL that the RI, let's say the reconstruction of the file. Because remember it's a byte array, right? No, or it's going to be a bad area when it's coming from the client over the API, so on to reconstruct it from a byte array into a physical image in our uploads folder. So let's get into it. So first, then I'm going to have is var URL, and this is going to be equal HTTP contexts accessor not HGTV context dot request, dot host dot value. So I'll call that URL, could call it current host, current URL. But eventually just talking about the, you know, like when we're running it from Visual Studio is going to be local host colon. That port when we deploy it to the internet, is going to be whatever domain name. So that's all that this is really going to be retrieving. Next up we want to construct our path. And like I said, or path will be coming from the web host environment dot web root path, which just gives us a direct path to WW root. And then we have our uploads folder. And then we're just going to inject in the vehicle dot image name, which of course should be passed over with all the information in the VGG object at a time of creation. Now we're going to get into the good stuff where we actually create the file. So we'll be using our files stream to do that. So we have VAR file stream is equal to system dot o dot file dot create. And then what we're creating is whatever image or whatever path we constructed here, we're just passing that the end. Then our file stream, we're going to tell it to write vehicle dot image. Now remember once again, image is our bite area, so that's our data. So we're seeing right, this data starting at 0 and From 0 to the entire length of the array. So conceptually, so seeing a write-off file, this beak, pretty much right, if you just hover over it, you'll see writes a block of bytes to the file stream. So any type of file it is, right. It's not limited to images, were just doing images here, but any type of file, we're just writing it to the file system. And then we close that stream once we're finished. And then what we're going to do is change the name of image at the object level. So we already have the name and we're using it for the path. All right, however, our new name, vehicle dot image name is going to be equal to https colon slash slash our URL, right? Or you could call it current host or host value, whatever you want to call it. But that is where our address pretty much slash, uploads slash and then the origin on the IM that came over through the API. So this is what will get stored in the database. And then we go ahead and do the regular insert and Save. All right, so I'm just going to put some space there that is creating the file on the API side or on the server side. Alright, so let's jump over to our form component for our vehicles. So I'm going to put in a new form groups such probably just puts it at the top. And I'll say that this one is for an optional image, right? So label image optional. And then what we're going to do is have an input file, tongue. All right, so you've seen the different kinds of inputs. We did this. We did number, we did takes. So nowhere doing input file. And then unchanged we're going to do a handle files and Exxon event handler. All right. I'm also going to put in an acetal peta there with a little warning, upload file warning. So he can just go ahead and do that. And then we are going to do the initializations below. So the first one that's, I'm going to initialize the warning. Now this initialize it. Don't need to change anything, right? No. It will only set it if the if the need for the warning arises right underneath this swan, we're going to have our private void phone Shun for handling the uploads, sorry, the file selection. So I have private void handle fast and like Sean. And then we have as a parameter input file change event R, and then R Tolkien, which we're just calling e. All right, so we'd know whole or events work so far we've only done live on valid submit. And so now we're looking at a custom event which is 45 selection. So whenever a file is selected, it will fire this automatically. And this is the datatype that we'll be storing all of the details needed on the event that is occurring, right. A case in point are going to have a file variable. I'm going to say var file is equal to E dot. I wanted to look at E. We see that we have file, file cones. Are we going to get multiple files? So if we were allowing the user to upload multiple files, you could just get all of them one time as an array or collection right here we are. We're only asking for one. So E dot file. But then we need to make sure that this file actually has content, right? So or because remember that if the clinic, even if they don't select anything, that event would've been fired. Right. So we're trying to get in the file, but then we still need to make sure that something was selected and then we can start our process. All right. No auto-fill been abundance of caution. Want to check our extension on the file. So I'm going to say var EXT, which is short for extension. And then I'm just going to do a System.out.println. Get to extension on the file dot Nim. Alright, so this file object has everything we need to know about the US right now with the content type, we have the last modified the name, the size of everything that we need. All right, By the way, this file data type is called eyebrows our file. So that's datatype and that is available for file upload in blazer, eyebrows or file. Next, we'll put in an if statement to verify the file extensions that we're catering for it. So in this situation, we only want JPG, JPG and PNG. Of course, based on your situation, you may want more or you may have different restrictions. But once again, this is all transferable knowledge and transferable concepts. So here I'm just checking if the extension that we just gleaned from the file name is if it contains one of our accepted ones, but I'm putting it to lower because sometimes files gets saved with all caps are mixed caps as the extension. So you know, just to keep everything on one level where forcing it to lowercase and comparing with the lowercase equivalent. Then in this if statement, if we are given one of the file types that we are looking for, then I want to create a brand new value for the peak, what I'm calling a peak ID, but it's really that that will be given to the picture. No. My scenario or my reason for doing this is, I don't know what fun name this user might have for any one of these files, right? I don't want to risk having clash between two files with the same filename either. So what I'm doing is generating using the grid library, good dots, new good to a string. And what happens is that a good gives you like a 16 character string. And some of these blocks of characters are separated by hyphens. I'm just replacing all the hyphens with a blank text. So at the end of it, you just get one big blob of seemingly random characters. If you're not familiar with what their gooey it is, that's what you'll get told off this. And then we're seeing vehicle dot image name is. They were merging that void volume with the extension. So this is what we want to call the file on the file system. Then I'm going to initialize a vehicle dot image, which is our military to a new by RE given the file.js size. So we have the file now, so we just initialize a battery, it's fall lot size. And then we're going to await file not open stream, dot read a sink and then vehicle dot image, and this is a scene, so that's why there's a line. So I'm just going to make this a sink void. Alright, and that should take care of that era. There we go. All right, So this is basically just going to say File Open up and copy or contents into our byte array, which is vehicle dot image. Now, this is if we get the things that we want. Otherwise, I'm just going to give Upload File warning. So some content to see. Please select a valid image file and let them know the extensions. I'm not going to put JPEG. You could if you wanted to, but I think that's clear enough. As a matter of fact, if we get the cart file, I just want to make sure that if the error was there before, that it was always. So I'm just going to initialize this or set the value of upload file warning destroy not empty if we're given the cart. So if it's MDRD and then it's still going to be empty. If you type content and we have the right one, then it's going to be empty. No, so that's fine. All right, So let's us take this application for a spin of artificial load. Majority of the form. I'm just going to go ahead and select one of my images here and then create the vehicle. And then we see that we are getting the new vehicle, but we don't have any way of displaying that vehicle, right? No. So it would be nice if we saw the picture right here on the page on the index page to show which vehicle it is. So we're going to jump over to the index page and made the following modification are going to empty new header in this table. No, I don't have to put image. I'm not going to put any text in the header, but we're going to have this new column, this new td that's just going to have IMG SRC being equal to vehicle dot image name. So remember image name is the path on the server where the image can be phone. So we're just seeing your source. Is that URL pretty much that we would have constructed from the API side. And then I'm just putting in a custom style to say height and width are 150 pixels. So I'm just going to save that and take, and when we reload our page, we see our image showing up. All right, so once again that is just embedding. Let me do an inspect element and you see that that is the URL https local host. So that's what we got through the context, access her sorry, the host value, and then the uploads folder and then that image file name. All right, So let us attempt to add one without the image. So Toyota visits, I'm just going to put in some dummy values to get through this quickly. And then we go ahead and click Create vehicle. And okay, So something interesting just happened. One. There's no creation. So clearly there was an error too. We actually saw that 500 page flush on and then flush off. So something is definitely 0. So let us go back over to the controller and we're going to have to make some modifications here. So the fact is that our code here assumes that an image will be present. So I think it's, it's giving me an error at this point because then it's seeing, right? Nothing because this would be null at this point if no image was selected during the file upload process. All right, so what we want to do then is maybe wrap this in an if statement that we only attempt to do all of this when the image or the byte array length is greater than Z. All right, so I've done that simple statement. If vehicle dot image dot length is greater than 0, then go ahead and get the URL, get the path, and do all of that fancy stuff all before we attempt to save. So that means if no image GameOver, then it will just operate as normal. So this step is important because we also want to take that into consideration on when somebody is updating the vehicle, they may have launched the update operation and changed the image or not, right? So when do we know when two genes. So this if statement could actually be reused right here. If that byte array has data, then it is a safe assumption that a new image is present. We have to reconstruct the file path based on the new name that was given to this new to upload that file, go ahead and update the data fields. And then ultimately we update the vehicle. Then you notice that all these lines of code are kind of repeating. So it would be nice if we created some form of function that kind of those all this heavy lifting and probably just returns that image pathname. So I'm just going to take all of these lines and I'm going to create another private function, don't. So this function, I've just done it so that you can always just pause and replicated what I'm going to walk you through it anyway, private string, I'm calling it create file path. I could have called it create file. It depends thing probably create file is a bit TR description does it is creating the file. And then what we're going to possible whereas the byte array of image and the string name, right? So I just copied and paste the code. That's why we have these reference arrows. So we're just going to swap these old. So instead of vehicle, the image name, I'm just going to say name. Instead of vehicle dot image, I'm passing image. And then this also would be image. Alright? And then at the end of it, I'm just going to return that constructed URL https slash slash the URLs uploads and then we're passing buck name. Alright. So what we can do then is we'll see if the image length is greater than 0, then image name is going to be a call to that function. So we call it Create File. And we're passing in vehicle. Dots. And the first one is the byte array, so the image and then vehicle dot image name. Alright, so that way we don't have to repeat too many lines of code is just one simple if statement and 19. So I think that this is far more, it's much cleaner and it's more reusable in this format. If we got an image that function call update this field by the time it comes back to here, we know that the file would have been created already and then go ahead and update. All right. So that is one issue dealt with, right? That's what was throwing the era when there was no image provided it through an error? No. The other issue is that we have our interceptor that mean jumbo, what's that it creates raise. All right, so this is a create for vehicles. And remember that we had setup our interceptors to monitor all the activities. So actually have a response here. If your code doesn't look like that, that's fine. That shouldn't be there. But we have this interceptor to monitor the old column of this operation and then take a certain action. So we actually saw the axon because you saw the red text flush on the screen, but then it still navigated to the index page. And that is what we don't necessarily want, right? So we have to make a small courage on here, where during the testing, during the implementation, I would have throw an exception at the end of this switch statement which I later. So we're going to have to put it back because what happened is that it hit this if statement. Of course, if you've got an arrow, that means we've got probably FIFO 100 a lot. One of the above, we know it's not a 40 for because it went to the resource. We know it's not the unauthorized. So that means it must have been a 500 and then it should have bones tool, the 500 page, but then it's bones there and then still navigated here. So we need a way to stop the execution of the application after this happens. And that sure-fire way would be to throw the new exception. So I'm going to throw an HTTP request exception. So this is HTTP request exception just, it's just going to have the message in it. Just to see that this is probably what went wrong. And so this will stop the execution after it navigates to that page. So then it wouldn't go this far. All right. Let us try that again. All right. So we're back on the vehicles create new vehicle page. And I'm not going to choose an image and then I'm going to go ahead and create vehicle. And so got that error. Apologize, this should be checking if it is not equal to null. All right, so I shouldn't be taking the length because if nothing is provided, then it's going to be null. So that's my mistake. Let's just make that adjustment so vehicle dot image is not equal to null. Then go ahead and try to do the create vehicle. Alright, so let us try that. All right, so we're back in the create new vehicles screen. We're not choosing an image. And then we're going to go ahead and create vehicle. So now that we've done that, we see that it goes into head, creates it, it successfully, and there is no image. All right, what we're going to do is just to make sure that our intercept works because we did this fixed on. I just want to verify it. So at the start of this creates, right? I think we'd run this test where I threw an exception at the start, but then that was in getting a list. So there was no actual code to navigate anywhere afterwards. So that's why I would've left activity without any red flags, but normally just throw an exception at the top of the post VBR. You don't necessarily have to do this step. You can just follow along. I just wanted to verify that or modification where once again filling out or form with dummy data and then I click Create vehicle. And then we see that we are landing on our 500 without being navigated away. So that is the expected behavior of this interceptor and how it navigates. All right, so we have adjusted that and that's just the parts of the process. And sometimes you will look something and then later on you find an error. But it's always good to kind of catch these things early. It's good that where, you know, going through this activity and then we see a chink in the armor and adjusted according. Alright, so one more verification and that is testing the update feature, right? So ds1 to go ahead and update the image for the Prius. And I'm just going to choose that nice blue roads that they are. Click Update and there we go. So you see creating works, updating works. There was no imaginal there is. Let me do it one more time. Because you know, the images, the backfill for a system, no, So we have all four images being displayed. Alright, so you can take that concept and go ahead and probably enhanced by the view screen. And once again, this concept is something that you can apply to other things when it comes to uploading files. Another good example, once again, would be requiring some legal documentation from the customers. Upon creation, you need ID, whatever tax identification numbers provided, you need an ID too much that specific one, right? Still fly at that. So you can go ahead and experiment with that. But you have the framework to follow. 41. Generic HttpClient Repository: Hey guys, welcome back. In this lesson, we wanted this course setting up an HTTP request repository. And all the context for this is there are a few things that we want to do and we have to continuously do when we make our HTTP client. Cause I mean, this line is simply NADPH. We weigh the client posts as JSON, JSON async, get the endpoints and we passing the object, it's simple enough. But then as your calls might get a bit more complicated. And in this situation, one level of complication that we had to put this interceptor one-way to this interceptor directly into every components, into the component or into the code behind. And then we had to make sure that this line was present. So I'm sure that was kind of annoying. And then if you have another one, if l another component or they are going to have to take that into consideration, they have to exit this and then usually into septa. And then if something changes, you have a whole bunch of things to cheetahs. So of course, it's always good when we put our code that we know is repeating in a more usable form, right? So in addition until the interceptor beating the HTTP client is being injected directly into each component. And then we have these function calls. And then if we have any additional information or hitters that we need to put on them would have all these components and modify once again. So what we're going to do is set up some generic repositories. So you would have seen the power of having generic stuff already from when we did our unit of force to form the API said, right, we said the poor generic repository and our units of work repository. So on the client side we're going to be setting up our HTTP client repository. Alright, soul. What I will do is create one new folder in the client project. And we're going to be calling this new folder, and I'm going to call it contracts, right? Because generally speaking you have contracts and you have services right down here, we call it iron repository and repository naming conventions. But essentially that's the same concept the of the interface which says this is what I can do. And then we have the implementation which does it. So we know by know that we tried to inject the contract into our applications like we did with the I unit of work as opposed to the unit of work. All right, So our contract here is going to be a new class. What I'm just creating art class. Of course you want to change that. I'm just calling it I HTTP repository. We go ahead and add that and then we change it from class interface. All right? And then this repository is going to take a generic parameter of t. We're just calling it t, where t is a class. That sure screed or T colon class. All right, so we're accommodating the different types. Once again, generic. So inside of this implementation, we're going to have a few methods. Get, gets that returns a list of t. So t once again is the object that we're requesting or the data type that we're requesting. So get through turns. One gets that returns a list and we could probably qualify this a bit more to say get all are getting list or something, I'll just leave it I get all four are null. But task that will create, which takes the URL and the object to be created. We have task the updates which days the URL, the object, and the ID. And we have tusks delete, which just takes the URL and the ID. All right, That's it for our contract. I HTTP repository know in our services are those reasons the services folder I'm going to add on kras and we're going to call it HTTP repository. Now, http repository, we'll have that generic or parameter. And it will inherit from HTTP repository, which also has that generic parameter. And then we qualify it where t is a class. And then we just go ahead and include the missing namespaces. And then we need to do that implementation of the interface. So now we have our method's created and are ready for, you know, fleshing out. So I will need to inject at the very least the HTTP client. And of course we know that we have the interceptor that we want present in every call. All right, so I'm going to do a constructor. And in this constructor I'm going to have the HTTP client and or http interceptor service. So I'm just going to go ahead and include any missing references and then we just initialize fields. So I've copied and pasted the field names with the on the scores. So let me just swap those oats. We are ready to flesh out what happens on a create. So let's just look back at what we did when we create. So when we said create mic, would Wanda interceptor, and then we would make that call which takes that endpoint, the appropriate endpoint and the object for the creation. So I'm just going to copy I'm not went to court. Well, I'm just going to copy. All right. And then go ahead and include any missing references. So MC method a sink. And we also need to include, well, we don't need to include endpoints. Reason mean we're expected to provide the URL. So I don't know what the object type is. I don't know what the URL is here. It was tightly coupled because you knew you were on make. So we knew to pass over that and that object. So here we don't know what the URL is going to be. So I can't use that hard value as it's coming from that specific components. I'm just going to take URL that's passed in when this method is called. And I don't know what the object is. Bullets, I'll just pass in OBJ and that's it, right? For the delete. What happens when we do? I'm just going to jump over to one of these index components. And then you can see here that I didn't even use the interceptor here. All right, so that's one of those things. So we want to intercept are present all the time. But of course it was tedious to be repeating it, but I'm just going to borrow this line of code that is relevant, so forth, the Delete, we're going to start off with our interceptor on the third this event, right? And this method Async. And then we're going to just see URL and the ID. Once again, it's not specific, so you have to keep the same format though. So URL slash ID, alright, for the gets, and I'm sure you're getting the idea by no, this interceptor must be used in every method. Because of course we want to monitor what's happening, right? And then we're just going to put in the appropriate calls based on what we would've done in the corresponding component. Alright, so I just went ahead and filled all the remaining methods. So for the get, we have the intercept term and then we return our weights client from JSON async, you might need to include a missing library, for instance, this one. But we include that and move ahead. We have the type parameter of type T because once again, we don't know what we're getting. And then we're seeing URL slash the id 4 gets all similar concept except we're returning a list and this should probably be more like Alice because we did see I list in the request, right, so I'll just return and that's fine. And the URL, alright. And then for the task update, we are going to see, put us JSON a sync policy, RL slush the ID and our object. One more thing that we probably should consider or we will have to do is the dispose, right? So we just wanted to make sure that we retain that this force. So there is an interface that we can include disposable. And then so we can have multiple inheritance from multiple interfaces in C sharp. And then that implements the dispose method right here. Others over edit with our code where we say into interceptor dot dispose events. All right, so next up we need to go over to our program.cs file and register our HTTP repository. So this is all we're going to do. Builder dot services are transient and then we're going to say typeof and then pass in the name of our contract, the eye HTTP repository, and then the type brackets. So because it's generic, the implementation or the registration looks slightly different from what we might have seen with the unit of work or distribution. Let me just bring that TO quickly. So when we did the unit of work, that's what it looked like with that I transient, right? So we have the brackets, this type of that type in this situation though. We're going to see open brace, typeof I HTTP or poster with the brackets comma type of HTTP repository with rockets. Note, once again, this is generic. We could get specific and actually have like specific implementations of repositories that specific Collie, sorry I'm spinning. See in specific color, but that directly mapped to the data types that we're using. So it could have the bookings repository, the colors repository. And of course that gives us the opportunity to extend the functionality directly for the particular type or different operations. Maybe bookings might need something else that the others don't. So the generic pattern might not necessarily work. So at that point again thing about having more repositories, but for now we're doing simple crowds of, so I'm just going to have the simple generic repository that everybody can use and enjoy and notice where I'm putting it. I'm trying to put it after the registration of the HTTP client and the interceptor stuff. All right, so now that we have all of that set up, we can go back to our components. And I'm going to start off with, we always start off with the simple one. So let's do colors, right? So in the create lotteries or file, we would have injected the interceptor as well as the client. Know what I'm going to do is inject the HTTP repository. And what we will have to do here is either we had the using statement directly to the component or we know that we can just add a using statement to the view imports so that everybody will have it. Alright, so that's something a can consider. But I'm just going to push ahead with the colors and this old. So because it is generic, we need to specify the data class, so I'm going to have to see color. Alright? And then others leave it as clients. So that means, okay, So this gets injected and then client no longer has posed as JSON dot a sink. No. Client will have a function call for create. And the two parameters will be the endpoint and the color to be created. I can remove the interceptor and let me just comment the mode for a no. And then let us take this horsemen. So we're going to attempt to create a new color and then see how everything ties together. All right, so let us go ahead. Bring home colors, create new color. And then I'm going to put in what's another common Caracalla? Let's just put in green. And then we create color, and there we go. So our HTTP client is still firing even though we're not directed calling it. And we have our repository know. So we have fewer injections and fewer points of contact and less maintenance overall if something changes, right? So now I can just remove those debtor references, remove that, I dispose inheritance and remove that injection of the interceptor. And then you can see that our component code looks a bit cleaner. So this is a nice little pattern that you can always think about. You know, anytime you're doing something over and over and over and repeating the code and then you're starting to add to it. And then you have multiple points of contact, then you can start thinking about how can you obstruct those heavy bits away from any one component or any one method or anyone class in general, and put it in a class for itself and reuse it. So you can go ahead and implement this. Then I would just challenge you to go through and refactor and update all of your references that would've been pointing directly to the HTTP client and the interceptor to know does point to the appropriate repository for that component. So when I said the appropriate repository, well, this one repository, but of course the Data class needs to be the correct one, right? Of course we already have the endpoints being passed over and the objects. So if you use the wrong one, then you'd get an error. So let's just take a look at mics. If I make this seem adjustment to the mix, right, I'm going to replace the client with that repository. Include a reference. Then I say color and then down here I see this should be created. Then I'm going to end up with an arrow because I'm passing in the wrong data type according to this, right? So you know that the Confederacy, if just to make sure that I add datatypes are always correct. And then you can just go ahead and remove the references to the interceptor and the disposable references. And then you can just do that to all of the other components accordingly. 42. UPDATE: Removing Magic Strings: All right, welcome back blizzard developers. In this lesson we're going to be looking at reducing our magic strings and all this operation is not unique to blaze a development. It's just good practice in general. And we will just be discussing one, what magic strings are on to why we need to reduce them. So starting off with what our magic string is, a magic string is any string that is pretty much hard-coded and it gets worse when it is repeated around the place. So a practical example of where we would have used magic strings would be like in our bookings controller for our API. No, these are much extremes. The dangers of using these magic strings would be that if I change the table name from vehicle tomorrow, there is not going to be any indication by the IDE that development environment that something changed on this might no longer be relevant or cart. So when I have this magic string hard-coded and I'm seeing vehicle and customer. And then maybe I changed the table name from customer because remember these are enclosed that needs to be included with the bookings. So that means there has there has to be a matching table with this name, so that name changes, then the code won't throw an error. And we won't know until the customer complaints that Hey, I click this button and it didn't work at that point. It's already not a good impression. All right, so we're going to be looking at how we can change these magic strings oats. And we're going to be starting off with our units of work. Alright, so the first way to get our own this will match extreme issue would be in the list of includes instead of hard coding, the word vehicle, hard-coding, the word customer, I could actually see name off and then put in the name of the class I wish to include which would be vehicle. So this would actually render a string representation of the word vehicle, which is perfectly legal in the form of the Includes, which is expecting a list of strings. So that means if anything changed on the vehicle class, maybe the name of it changed or something like that, then this would definitely throw an error because there would no longer be a class by the name vehicle. However, this is a good solution, but it does not necessarily fix the entire scenario, at least relative to our need to include additional properties. Because if in the bookings domain class, if I actually change the name of the property from vehicle to save the coups are car or something like that, then there would still be no indication at this level that there's no longer a navigation property to be included by the name of vehicle. So what we're going to be doing is changing old the mythos off including. So instead of using a list of string, we're going to be using a different data type called an AI queryable. I include a query of all right, That's, that's quite a mouthful, but it's going to look similar to our ordered, I ordered queryable. It's actually a very similar looking datatype. So I'm just going to go ahead and replace in our generic repository the list of Includes to know be. Alright, we'll get to it. It's going to have the same first part function, our phone angle bracket I queryable t, it's the same thing except the second part is I include queryable t comma object. All right? And then that's really just the function. So it's returning something like a function. And I have to include another dotnet core library. So that's the whole problem. And then we would have replaced that barometer heart. So that's gets also have to do that again for the Git. So I'm just going to go over to the get and in replace that also. Now that's in the interface, of course, whatever we are doing, the interface we have to do in the implementation. So our implementation is not happy right now because we changed something but not to worry, we'll soon get up to speed so far our GET, we do the same thing. I'm changing this to our incredible queryable, and I'm going to go ahead and include the missing references. Then the same thing for the gets all. I know that we've done that we have to refactor quite a few things. One, our method's on to every other method that was calling this. I'm using that includes parameter. All right, so no, inside of our implementation on the way that the include works null, it is a myth odd. So we don't need to go for each through every property and try and include it. Instead, what we're going to do is just remove this for each. And then we say query is not equal to the Includes, which is once again a method. And then query. All right, so pretty much when we pass in an object which is going to look similar to a lambda expression, similar to hold the orderBy looks and so on. But when we get there, we get there. What's going to happen is that if anything came in, in the upper mantle, which we're already familiar with the concept of. Then the query is going to go ahead and execute that includes parts of it against itself. And then we have that query with the included permit. Those are data rather, right? So we have to do something similar in our gets all where we just say queries equal to execute, that includes against yourself, please. Just the same way with the RW. Notice that the order BY who was doing the same thing. Well, that's what the inclusive doing. All right, I include double queryable. So now that we have that, I'm going to jump back over to my bookings controller. And now we see that all I was kind of chaos has broken loose because our includes parameters no longer list of string. So I can actually just remove this, right? We know we need vehicle and customers, so I'll do it with this one that we haven't modified as yet. So for the include spirometer, we're going to be passing expression. So I went to see Q and a startup that lambda, lambda expression. And I can now see include. There we go. Now include may come up, but it's what I have on there. You just go ahead. And if it does come up with an error that you can go ahead and include the missing references are. So when I say include here, I can put another lambda expression inside that include expression and then start including the actual, the actual navigation properties of the booking class so that we, we know where talking directly to the class as opposed to Hopefully third, putting in a string and hoping that it matches something in that class. All right, so I can know C, I want to include vehicle. And guess what? I need to include more than one thing so I can just ci and this along and say dot include again. So notice I have included and then include. Right. So if you need it to include this property and a child of that property, then you can see include, dot then include and you keep on going down to achieve. But for every time you say include, you're looking directly at the class in question, at least in this case booking. So you're only looking at the booking properties as you go along. So I need and I need customer. All right. Let me just break that down a bit into different lines so that we can see exactly what's happening. And there you go. So it's all strongly typed. So if anything changes in the booking table, it will definitely bring the code just to say we would change the repository and all the code is broken. It's good when it gets broken at this stage because then you fix it. And then you can go ahead and publish your application with more confidence. So I'm just going to go ahead and replicate that include statement up top here because we know that that's what this one needs. Also, remove that list and let me just make sure get rid of all the arrows I wrote includes colon twice. All right, so that is one problem fixed. All right, so I'm just going to do a build and see where else may be broken and our error list, thankfully it short, right? No, but we can see here would be another place where these magic strings could cause a problem. All right, so now I can just see dots includes, and look at this. I'm using the same code that I used for bookings and I'm getting errors. Why am I getting errors? Well, one, navigation properties not inside vehicles. So that's wrong. Customer is what vehicle is not either way. And well, I wouldn't be including the consent of equal. So the problem with this once again was that if I had put in name here, that's a vehicle and there would be no indication that this cannot work until the program crashes. So this will actually save a lot of time in debugging and Preventing books from ever occurring at this stage, right? So now I can see include the mic. And then I can see that include again. And this one would be modeled on call. All right, so now we have all three of those being included, and I'm just going to copy the line and use it below, also includes colon and then our statement and then I can get rid of these lists. All right, so ultimately, that does help to clean up a lot of your code, make it more bulletproof as you go along and it grows. Now another area that I want to address, a magic stream that could cause problems would be inside of our booking object or dummy an object where we have this validation being carried out. Though here, I'm seeing that this is our message and it must be applied against this property. Once again, if this property name changed, well, that's too much of an arrow. But if this property name changed and then we changed it here and we changed it there. We could easily forget to change it there because we're probably more attracted to the red lines than looking for every pleased that we said the word or the words date in. So my point once again would be, and we can in this case use the original method that I've shown where we see name off and then please the name of the property in that. So this will render to a string. So if anything changes in the name of the property, that red line will also alert us. So those are little development tips. Once again, this is not business specific, this is more just general development guidelines to make sure that you are building bulletproof. So applications and that they are more maintainable for the longer run. 43. IMPORTANT - Fix Delete Endpoint: Hey guys, I just have a quick addendum to the previous lesson where we would have refactor our code a bit and remove the constant magic strings as they're called when we're calling our endpoints, however, that bits of refactoring and the way I wrote it kind of introduced issue with the delete. So what will happen if you wrote the code just like I did, you would end up when you delete this, this endpoint would return a 404. And the reason for that is I created the mix endpoint static string with that trailing slash. And then in building the URL, still put us slash. So that would mean that you would have api slash, slash slash than the ID. And then that would actually make it stop working so easily. You could fix this by maybe removing that trailing slash on the API and on the under static string rather you could just remove those trailing slashes. So that way when you're building new URL, you can put that slash. Or if you want to leave the slush on the static string and remove the slash there. But I think it's harder to kind of see that working or you know exactly how that works. So I'm going to remove the slushes from the API endpoints. And then in forming the URL itself, I will put that slash there. 44. Progressive Web Application Support: Hey guys, welcome back. So we're here to talk about progressive web applications. No, progressive web applications are PWA for short. It is persona refers to web applications that make use of modern browser APIs and allow you to create downloadable web ups. So let that sink in a little. So when we say downloadable web apps, these web applications, much like orbiting is up here. Remember when we were creating it. And I made sure to point out certain options. And one of them was progressive web applications. So it came with certain files that support progressive web applications, namely the worker service and those those JS file as a manifest JSON. All of those are kind of included because we chose the progressive web application. All right, so in order to download this web application and just, just the 0 that this is available in chromium based browser. So as you can see here, I'm using Microsoft Edge. I've been using edge. What? Microsoft Edge at least at the time of this recording, is based on Google Chrome's Chromium Engine. Google Chrome is the pioneer for that technology. Opera is also based on that technology. Not entirely sure about Firefox's support for progressive web applications, at least at the time of this lesson. But we can use edge and do a proof of concept. So in order to download this APP, all we need to do is look for that little building block up top here in the address bar and see when I hover over it, it says Installed current management. So that's the name of our app we've been building. And I can just go ahead and click that. So the thing is that this up is actually like a modified version of a wind farms up that-that done in the past. All right, so this is actually making, it's web-based, but there are certain people who just like having the apps on their computer. They wanted to sometimes work in offline mode. And all of those things can be made possible for web apps through this progressive web application technology. So when I go ahead and click Install into actually just take a few seconds and put this application on my machine. So here's the application on my machine. And you can see it's not earning in the browser anymore. I can always click this. Go to info. I can open it in the browser if I want. I can uninstall. I can even cost media device, it's on my machine. All right, and there's the icon in the Start menu bar. You probably can't see it. But I'm actually hovering over the icon down here where I can actually just pin it to the taskbar. There is the icon. Alright, so all of those files, the manifest dot JSON. Even when I stop, let me stop and let me jump over to these files. The manifest JSON here I could change the name of the application and the short name, all of those things, the buck grown color of the icons. There are a number of things you can do from these files that that influence what is presented when this is downloaded. So that's that icon, that's ash that came up on my application having installed it on the computer. All right. So if we change that o to maybe the company logo or so on, right off the bat, when it installs, that's the image that will be displayed. And once again, he can make all the changes in these files. But I just wanted to 0 that just all tough the box just by selecting a few additional options. When we were creating this project, we had indicated, and we were so graciously granted the opportunity to use progressive web applications with our blazer up. So now we can have a hybrid situation where web a web up, they can easily install on a Windows device, on a, on a Linux, on a MAC, on an iOS, on an Android, it really doesn't much at once. We're using a modern browser that supports this technology. 45. Add Changes to GitHub: Hey guys, welcome back. And we're at another checkpoint where we're just going to be checking in our quota GitHub. But before we do that, I want to review some of the major talking points from the activities that we completed together and point out some of the caveats because I showed you some stuff and then I kind of left you to finish it up. I encourage you to finish it off yet all of course, have my cool to reference, but just in case you're running into any difficulties along the way, I just want to point out certain things all to you. And that's what we're going to do before we go ahead and move forward. So by way of recap some things that we had done in this Section 1, we started off with customizing the, or at least looking at how we can go about customizing the identity pages. We saw that they all got generated where we scaffolded them in the identity pages section. And we saw that we can modify the login or register. We can extend them according to our business rules and requirements. So you have a good idea of how to do all of that. We also looked at implementing JS interrupt with third-party libraries. So I'm just going to go with the bookings page where we did that on the index page. All right. So another thing that I would have done is to make sure all of the components have code behind file. So once again, this is actually optional, so I'm not saying you should or if you don't have it, you haven't accomplished anything because if it works, it works and it's worked it's designed sorry to work in either format. However, I have gone ahead and imported every single components score over to the code behind file. All right, so for the index page, we have to implement the AI disposal because remember we have that dispose method that we implemented. So in the component itself we said I disposable or I dispose dot dispose. In this situation, we're just going to inherit it and then use it, and we've done that before, so that is nothing to foreign. Otherwise, we don't know. We have our injections as we go along, we do our JS Runtime and on after under a sink, we go ahead and render the data table. We've gone through the school before, but just as a recap, we know, we know, know what it takes to implement or put in a third party JavaScript library in our blazer applications. So this technique goes across the board for basically any third party JS library that you want to implement here. Now another thing that I would have done off camera is implement some level of security. So there is a security policy called what It's called content security policy, where we can go ahead and place restrictions on the scripts that we want to be run on our application. Now this policy is not unique to blazer, it's a web policy. I'm just implementing it in blazer here, but this is what that policy needs to look like so you can pause and try and replicate it. But I went to walk you through it. So the metatag, HTTP dash equiv. Content Security Policy. So it's just a header that we're sending to the browser to let the browser know what script files, what CSS files we want to run on our application. And this becomes important in helping in the fight against cross-site scripting attacks. So this policy just goes ahead and sets up restrictions. And it lets it know that anything that is not coming from the website itself or including this particular code or has an unsafe evaluation and don't execute it. We also let it know that we are trusting scripts from these sources. And similarly for the styles we said, Okay, we'll accept self. We can accept inline styles, and we'll accept a style sheet from here. So Nevada third party, so pretty much if we are going to go ahead and include other third party libraries, and we want to protect our website in the same manner than we would just have to extend this metatag to include those things. No, content security policies are very popular method of securing websites. Again, read up more about it from even Firefox's website, which I have just brought up on screen CSB. And you can just read up on it and see exactly what kind of protection you can get and watch these values really mean in constructing this policy. Now moving on, we also went ahead and modified or in septa service when we were modifying the file upload. So we're testing one thing, unfold another loophole. But we went ahead and added this exception to the intercept 0 because we needed it to stop execution once there was an error, because it would actually continue to try and execute. So we needed to stop it in its trucks and let the user know that something went wrong. And in that same notes, we had implemented file uploader. We did it specifically for the vehicles. And the forearm component for the vehicles is much bigger than the other form components because it has a little bit more logic happening in there. But once again, this is just how we can kind of isolate the component code into the file so that everything stays compact and easy to find, right? In a bid to reduce the repetition and home in the tens or calling the client and the same method over and over, well, we did was create an HTTP repository, which I just call it an HTTP repositories generic enough to accept any datatype and carry out the action required, know some things that I want. Some decisions were made here that later when I was a refactoring came back to haunt man, you probably either have gone through its R, are going through it. So let me just point you told in implementing a put this as an idealist, but then, you know, I cannot mix them much. I list and list through all the code. So that would have caused some conflicts. So either you change it to list and then change everything else to list or change this the idealist and everything as the analyst. Either way, that little datatype mismatch might've caused a few headaches here and there. But my easy fix those to me at this list because most other things we're just list in my code anyway or in the rest of the program. All right, so you can go ahead and look out for that. And you would also see that if you made the repository and list, then it's actually easier for you wouldn't have that datatype mismatch for the ones that are list, right? So like I said, I'm mixed and match them. That's not necessarily a good practice. When to clean that up, of course. But if you're using a list USA LLC, if you're using list useless. But the good thing about idealist is that it's just an obstruction of a list or collection type that is list. So because we're returning a list from our generic repository, it didn't cause a datatype clash because we're assigning the L2. It's an abstraction, It's higher level obstruction. Alright? So that is relatively unknown is yeah, I'm just pointing that old in case you are wondering. And then finally we explored what it takes to have progressive web application, how exactly it works. There's much more to it. What I'm not going to get too in depth, but we saw how easy it is to just install it on the machine or on a device. And we can customize the images and certain bits of information from these files that are in the www root folder. All right. So with all of that said and done, and that's us go ahead and do a check-in. This is a huge check-in for me because of quite a few files that were modified along the way. And we have the images and all of these wonderful things. So of course, the riots or friendly and useful message that depicts to yourself, to future you and to your team what exactly was done. And then I'll just do a commit and push. So a push of course a sends it wonder, Shauna sink means that if there are changes up there That's idle on top, then it will pull them don't also, since I'm the only one working, it doesn't really matter which one is used. So that's fine. And that's it for this section. See you. And that's it for this section. See you soon. 46. Deploy to Azure: Hey guys, welcome back. So we're at this module where we get to deploy our application to Microsoft Azure. And Microsoft does your is the flagship Cloud provider by Microsoft. And what they do is they provide the ability to deploy your applications practically seamlessly to the internet. And they provide managed infrastructure so you don't have to worry about going and configuring servers and sitting up this and security that they give you all of that out of the box. And it's relatively affordable. So we're going to be deploying our application as you see it here, to Azure. I have in another tab linked to Azuri. You can get there azure dot microsoft.com. And what they have, first thing that you're going to see is that you can get started for free. So it's really easy to sign up, especially if you already have a live of cones, which you probably used when you installed Visual Studio at the beginning of this course are in the past price of this course. But it's easy for you to sign up, get started for free, you get 12 months, as well as 200 dollars credits to go towards services and experiments that you want to. Now, personally, I have a pay as you go up, which means that I only pay for resources use. So in this tutorial, some resources will not be free, as in if you're on the free plan, that's fine. But if you're if you're already exhausted your trial period and then you're doing this course and you're deploying that you may have to end up paying for certain services, which I will point them all. It's as we go along and tried to keep everything at the bare minimum. But if you can't necessarily follow along and bullseye do at least we'll see how it works deploying an application on to Microsoft Azure and it's pretty easy. So let's get started. No Buck in our project, we have some prep work to do in our configurations before we can think of both deployed in our AP settings.js JSON file. We need to configure a path. Well, we need to set up an SSL certificate and configure it spot for our identity service. So what happens is that based on the configuration that identity server has altered the bolts, we need to configure an SSL certificate so that the client application can actually speak to the server application. All right, because then it's going to fail on the startup. So actually had a little bucket with the sum does skipping ahead of the buckle. And I'm just showing you the solution to that very, very prevalent problem that you might end up having if you don't follow these steps. Alright, so the client application needs to communicate with our server with the identity service. It needs to basically do like behind the scenes, sign in so that the client knows or the, sorry, the identity service knows that the client is here, it's ready to connect. This is done over a very secure connections. So an SSL certificate is necessary to facilitate this. So in development, that is fine because in app settings that development dot JSON. You'll see here that it says the key type developments. So it just says, okay, well, this is development moment, it's no problem however, in our upsetting. So you don't have any setting like that. And we do have the client where it says this is the client that's connecting the profile is that it's an identity server, SPA. And if you go to the controllers and all IDC configuration controller, then you're going to see where all of that client stuff comes in. So this control and abroad, it didn't make much sense at the beginning of this course. And I didn't spend too much time explaining what was going on here. But then based on all of the interaction and all of the things that we've done up until this point. And you see how we have to authenticate against the server obligates on our gains. I had entity in order to use the client successfully, the Tolkien needs to be easy at all of those things. So this controller basically just pulling those strings. It knows where the client ID, once again, this plant, right? It knows all about all of that and it is basically just facilitating that communication. But once again, SSL certificates has to be present. So facilitate this. Now in this deployment, we're just deploying a personal application. So the cert is going to be a self-censor that we're going to generate on the machine and then use. But in a production setting then of course you'd want to use a production ready and properly issued certs by one of the leading authorities. However, the concepts will remain the same. So let's just get started. So now to get started, what we want to do is bring up PowerShell are going to be using this very powerful tool. Once again, if you're on a Windows machine, but it's a very powerful tool and we're going to be using it to generate or SQL scripts. So you want to bring it up as administrator. All right, So Run as administrator, you can either search for it in the search bar or you can find the icon itself Right-click and then you see you run it as administrator so you can use either option to get that building. All right, so the first command, and what we're going to be doing is building some. So if this is the first time using Porsche easily gets a C, kind of how it works. Well, well it wouldn't be the first time using bullshit because the package manager and visuals student is actually using PowerShell commands and commandlets, right? So that kind of format get dash help or the dash database and add dash migration. All of those are what they call PowerShell commandlets, right? So here we're going to use a command led to create a new search. So this is a variable. Alright, if you don't PHP that shouldn't look too unfamiliar to you. And then we're going to say new self and then he can press Tab and it will auto complete the line, right? So Newell self-signed certificates, DNS, name. And then I'm going to call it, let's call it car in tau was car or a towel Watson, right? That's that's what I'm caught in the DNS. So generally speaking, that want, you want that to represent the URL for the website. Once again, this is just deploying or on up. So the concepts are there, even though the practicality might not necessarily apply in a real-life situation. All right, so DNS name, I'll just call it car until Watson or you can call it something you're more comfortable with. The cert store location. So it kinda default location is cert colon About slash local machine, which just contextualizes and this is all right. And then we just, how large that just seen cases, they'll be too small. There we go. That looks a bit better. Alright. So you will self-censor DNS name car until wasn't CERT, cert, store, location, search, local machine, cert colon slash, local machine slush. And notice the direction of this slash, slash my right. So then it creates it, and then it stores whatever details inside of this variable called CRT. All right, then we need to foster protected. So we are going to see PWD and convert tool, or sorry, convert tool, secure stream. There we go. Dash string, and then we'll just give it a string. So I was going to use the default boss or that we know and love. Of course once again, you'd use a much stronger password in our real life situation. And then we have say a force and as pretty and texts press Enter. So we're storing the password as PWD. Then we're going to build the path. So five is equal to, and then we say sir colon. And then if I just press Tab, it finishes local machine M tub, say Candace, use the top to kind of speed this along. I'm only doing this slowly so they can follow. And they say cert dot thumbprints. All right. And then we're going to having built up all of that exported to a physical file. So I'm going to say export dash b, fx, certificate, dash CERT, cert, and surf is fallen dot py. And then the file path is where we want it to call, right? So I have a file path at c colon slash slash sh. Okay, let me just do c colon certs. So that's my folder on my machine. So you can go ahead and create your own folder on your own machine. And then you can use that file path. It won't create it for you, so make sure that it exists. But you want to give it the file name so I can see blazer wasn't cert, then we just call it dot, dot p effects. All right, so that's the file that I wanted to generate. And then the password is the There'll be all right, go ahead and press Enter, and then it will show me that the search has been created. So for ease, once I'm going to do on because there are two reasons I'm going to do it this way. One, for ease in on quick wins. So we're just going to put it into the project. Will we know where it is? And we're going to also put in the connection or the details of bulleted in our clinic, in our app settings, in our configurations so that it can be used. I'll turn it to pole ever. And probably the way you probably really want to do it in our real-life secure setting would be two. When deploy, when it is deployed as your uploaded to Azure, let us manage the certificate and then set up your configuration to see the certificate as managed by Azure. Now because I wanted to keep everything kind of low-cost, I won't be spinning up the paid version of Uzziah that allows all of that to happen. We'll be using the free tier. So because of that, I'm going to keep it simple. But once again, the concept is there. Alright, soul. Let us import this certificate into our project. And all I did was go and find it on the file system and copy it and paste it into the project. And here it is. And what we want to do is change the properties to make sure that it it sorry, it copies always. You can't say copy if newer, that's fine. All right, so what happens is that we want when we're deploying that it includes that in the deployment. So now all we need to update our configuration so that the identity server knows where to go and find that certificate that should broker that connection. Once again, this is so that we can get through this activity. But the prob, the more secure way to do this would be to let your manage the key and then have the configuration point to that managed key. All right, so that way there is no physical F0, F4 key for anybody to be able to access. And of course, I mean, this way can be secure if we just lot bone to access rights to the service and nobody can really access the physical key file and anything that bullets, you know, probably better to just manage it because Uzziah wouldn't know best. So here we're going to put in some configurations for keys. So inside the identity server configuration object or JSON object, we have clients, and that's our clients and so on. Our clients are going to put a comma and then key. And then we say colon and then open up a new configuration object. And then we're going to specify the type, the store name, the file path, and the path. And that's what that looks like, right? So we have the type which is file. All right? If it was being managed by a 0 type would be different. So we have type which is file store name. We'll just call it my file path, the path that assert. So I've just put it at a root of the project. I could have put it in a folder, whatever, but wherever I put it, That's the file path and the password is the posture that was used. Alright? If anybody accesses the sponsored and can access the file, then obviously, you know, somebody could break it down. But once again, this is a self-signed cert. So the whole idea behind this is not being the most secure and being more secure costs more money. So in this situation, we're just keeping it low cost once again. So after we've done all of that, then we can go ahead and deploy. So I'm going to go right-click the server project, click Publish. And then in the published screen we're going to say start. So from published we can always just send everything to a folder, put it on us, a local server and have run it. We could deploy to Azure, which is what we're going to be doing. Depending on institution you may want to choose one of the above. Well, once again, we're focusing on azurite and also it, it just floats in next. And then we want an app service will keep it up windows, so on, change that Next, and then they will confirm your subscription on. So at this point you might be prompted to login. You can go ahead and do that. But the semi-colons using for Visual Studio is my Microsoft.com and used on 0's. So they know me, they know which subscripts, so on. And you have pay-as-you-go dev slash test where you only pay for what you use and you get the resources at the slides or lower cost. But of course you're not using them for enterprise reasons, right? So that is my subscription that I'm on. I have more resource groups, or resource group is like a container, like a logical container that says all of these resources belong to this up. So you tend to want to have our resource group per up. Alright? So I'm going to go ahead and create a new resource group. Well, actually I'm creating, so I'm creating a new AP service, which will then suggests that resource group for that App Service. And App Service is a managed server. And I keep on seeing managed, managed meaning that you don't have to worry about the infrastructure and installing Windows on configuring IIS. You don't have to worry about any of that. Everything is preset. The environment is they're basically saying I have the environment, just give me the files and I'll do the rest. So we can give it a name. So we can probably change this to say like current wasn't current, blazer, something, whatever the name is that you would like based on what your company wants. Resource group. You can leave that by default or if you want to create, then you want to have a specific name, then you can do that. The whole steam plan noise where we need to change it. So I can click New and we can select one the location. So based on where I East US 2 is my closest data center. But then you see that they stayed there for quite a few geographical locations. I want to choose the one that is closest to you to have the most efficient or on right? So after choosing East US 2, I choose which plan I want. And of course the magic word is at the top, the free one. So I'll go ahead and click. Okay. And then we can click Create and then give that a few minutes. I said minutes, but it really took less than a minute, at least for me. But at the end of this activity we have the absurd is created. Then I can just go ahead and click Finish. So the resource is there in the workload. It's sitting known waiting Web, deploy it as yet. Well, we have another loose and that we need to tie up, and that is our database, right? So I need to configure the needs of bees. Are we using Azure SQL or are we using an on-premises database? And all the Azure SQL Database is another version of manage software. The T care of all of that for you. They're just seeing Tell me what do you want the database to be called on out created for you? All you have to do is create a table is read and write and leave Mary, you don't have to worry about installing encirclement environments on all of these things. So we'll just use the Azure SQL database. Click Next, null. The database needs a server, as we know, right? Use the deeds of B as we have to have a server and please, so we have to actually create these. And then that this step is where costing comes in, right at. This step isn't necessarily free at all. All right, So database name, we'll just leave the defaults, current management dots Server DB, where the needs are being served. Well, this is a database so we need to create the server. So after gotten you again, so the servers or at a cost and really comes in because annoy, you have to pay for that space. And I'm just going to call that DB server just the nice generic name. I don't want it to be too specific as it does a server that is going to have many different old spit that's not available. Current management, Watson. And this is a slot at the Watson ofcourse is sharp for WebAssembly so that it sounds as accepted that one East US 2. So you'll want to keep all they'll few resources into CMD geographic region. And I'll just use true war as the username and p sin Dala sand dollar sign W 0 RD for the password, the same dollar sign, dollar sign W 0 RD. Alright. That's all that's needed to set up a brand new service. You'll easily that is no, if you were to install Microsoft server on your machine, it Bravo would take a little bit more attention than the simple form that kickoff an Okay button and then clicking Create. And then this one might take awhile. And when it's done, we will have our database server and database created Android for you. So we can just go ahead and hit Next. And then they ask us to confirm the connection string. So this reuse the same true war and P sign, dollar sign, dollar sign W RD. All right, so then they give you that connection string value, which you can always just take a peek at any can copy it and keep it for your own purposes. But this data source is the address to the server. Well, yeah. So the database server. All right. And that's the name of the database. You know, a bolt connection strings already. But you could actually just open a SQL Server Management Studio, put in this value and then authenticate and then connect. And the good thing is that it's automatically secured so as your Has it has blacklisted everything. There is nothing alone. So if you tried to connect from your machine, it will say, well, I see your IP address, but he's authenticate and then indicate that you want to be white listed so that we, you know, unauthorized accesses is caught don't significantly because of that default security policy on your database. I'm just I'm just trying to show you how cool is when it comes to keeping the save. And then ask, where do you want to store your connection value? I'll just leave it in app settings. Key Vault is a paid service. If I'm not mistaken, as your app settings that comes components, of course, you have one that works and then one that is very secure, more secure. So we'll stick with the one that works anyway. All right, so let's go ahead and click Next. And then they will suggest that we need to deploy some dependencies on acetyl-CoA Secret Store so we can hit Finish, allow that to do its thing. And then when it's done or published pitch know has no warnings that everything is good. But I want to make one modification before I hit Publish and that is to the options on Publish. So I'm going to hit Edit. And then it brings up this new dialog box that we didn't see before. But I'm going to go down to settings and then it's going to discover the databases ended up contexts. What happens is that at this point it will create the beats obese, but there will be no tables and no data according to our C, that data and so on, right? So I'm going to go ahead and let it know that I want it to apply this migration on public, on published, sorry. And we can choose to use this connection string at runtime, right? So I'm just going to take those to the other settings. Don't really tinker owed them. We can choose to install this extension. I'm not sure if that's a paid service, to be honest. And then we can choose that everytime we publish 12, clean out a folder and republish. Probably don't need to do that one. But I'm going to leave all of these ticked and then go ahead and save. And then the moment that we have worked closely for, let us hit Publish. And when all of that is done, we are getting this 500 error. Her at least there's progress. So what I'm going to do is sign into the portal. So this is my portal. This is what it looks like. Hello, you can customize it, so don't mind how boring my dashboard looks at are either have without many resources anyway, but I'm just going to go straight to the App Service. And from there I'm going to use the side menu. So you can, I mean, if you have this area, but to look at it, you can take some time and appreciate that you're getting different metrics, the attain data. Often you hit a 500 error. So you see we just hit one. It's a very useful dashboard. You can restart again, stop it, and delete it a number of things, right? So what I want to do though is get to some advanced tool. So under development tools go down to advanced tools. We can click Go. And then this will bring us to a dashboard that allows us to go into the actual file system, right? So I can go to a debug console, cmd. And then here I can actually view the files that were uploaded. I can go to sites www root, and then these are the files that were published. All right. So you see everything is right there. Alright. So I want to know why this is feeling. I wanted to see in love someone to modify the web dot config, which is at the very bottom of this list. And then I'm going to tell it STD logo enable is true. Save. And then I'm just going to try and burrows through the websites again. So say I have some searches open from another activity. So SS Refresh. And when that refreshes done, that means it would have generated a new log, someone to go buck. And the log destination is this log files and there's our logo, stdio dot, dot, dot, dot. Look at it. It says there was an error loading the certificates, the file. See Holmes said WW root, blazer, Watson cert was not phone. So that is why so just to drive the point home that we need to have this certificate to running because you would have seen another arrow if the circles and president and know that we told that the search is present, it can't find it, we're still getting an error, right? So the search is absolutely vital. Now what do we need? What I need to do is look back and see why it cannot find that cert. So it's alright, so I'm going to say Copy always. All right, so it seems that's a copy all is. And then I'm going to do a fresh publish. And when it finishes that published that time. Boom, there we go. So we have published our blazer WebAssembly up to the internet. There's our URL current on management wasn't websites.net. Of course, you can buy your custom domain and how it's setup properly. But let's try to love and wherein. All right, here's what we need to fix that style, but standing aside, you can always fix it up later on. But here we are on the Internet, so we have our mix, we have our models, everything that we had seeded into the database when we started off is there. And then we can go ahead and do our work as we wish. All right, so we have successfully deployed our application to the Internet courtesy of Microsoft as 0 and you see, it didn't take on our right. That's how easy it is to deploy an application to the Internet using Microsoft Azure. So that's it for this activity. Thanks for joining me.