.NET Microservices – Full Course for Beginners

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
learn the foundational elements of a microservices architecture with net by building a real microservices-based application julio is an excellent teacher and has created many popular.net courses welcome to buildingmicroserviceswith.net the basics my name is julio gasal and i'll be your instructor through these first steps in your mac services learning journey with the.net platform before we move on to learn about microservices i'd like to walk you through the fictional client application that drives the requirements for the backend system that you will build the high level architecture of the system and the technology stack that will be used across this course let's imagine a video game where the player will need to acquire a series of items to stay healthy become stronger and survive the multiple changes that await him in his adventures there will be a series of stores that will allow the player to purchase items like potions antidotes and even source and shields these items have a price to purchase them the player will need to present the right amount of some sort of currency that we will just call jill once the player successfully purchases an item it then goes into his inventory back where it will be available for him whenever he needs it now the client side of this game the app that runs in the player's device is already being built by your company's client team so you don't have to worry about it and in fact this client app is not part of this course our team has been chartered with building the backend services for this game which the client will heavily depend on to be able to store the items catalog the player's deal and inventory and to enable the in-game purchase experience let's now look at the high-level architecture of the system support the client applications the following microservices-based architecture has been designed at the core we have identified four microservices catalog which owns the list of items available for purchase inventory which keeps track of the quantity of items that a player owns identity which manages the list of players and also acts as an identity provider and trading which owns the purchase process that can grant inventory items in exchange for jill each of these services have their own database that has no relationship with other databases and that are of exclusive use by the owning service for inter-service communication the system makes use of a message broker which allows the services to collaborate by polishing and consuming messages asynchronously for the clients to interact with the microservices this architecture has an api gateway which provides a lot of flexibility to make changes to the services without impacting the clients and lets the services focus on their business while delegating multiple cross-cutting concerns to the gateway there is also a front-end portal that enables the administration of the items catalog the players and the inventory and it also includes a store section where players can purchase items finally there are a few infrastructure components like logging distributed tracing and monitoring that all microservices can interact with and that can greatly help to troubleshoot issues and make sure the whole system remains healthy now there are a lot of topics to cover to implement this system so in this course the basics we will focus on the most fundamental parts related to microservices collaboration in that sense you will implement only the catalog and inventory microservices using.net and asp.net core and you will use mongodb to host a non-sql database for each service you will initially explore how the services can communicate synchronously via res and http but later you will stand up a rabbit enqueue message broker that will allow all services to communicate asynchronously by publishing and consuming messages via the mass transit distributed application framework that will give you a solid understanding of how to get started with microservices and net and how to tackle the multiple challenges of getting the services to collaborate in a resilient way the frontend portal is placed on the react ui framework you won't be coding this portal but you will get access to all this source code so you can build and run it in your box and use it to see how real and modern client can take advantage of your microservices also you will run all infrastructure services like mongodb and revit queue via docker containers which is the best way to get things up and running in your box very quickly at the end of this course i will point you to the next steps so you can continue your journey by implementing the rest of the system in the next lesson you will download and install the first set of tools that you will need in your development box for the upcoming models in this lesson you will set up the development environment that will be used across this course here for the tools required for this model the net 5 software development kit or sdk which includes everything needed to build and run.net applications docker desktop which has all the tools needed to run the multiple infrastructure services that we will use across the course and visual studio code the lightweight but powerful source code editor that we will use to write build and debug our microservices code a few of the future models will require more tools but for now this is all that is needed let's go through the installation of these tools and the overall setup of our development environment before getting started just keep in mind that the pages that you will see for downloading the tools will likely look a bit different depending on your operating system and the versions available at the time that you're taking this course but regardless the result download and installation process should be mostly the same so let's start by going to the download page for the net sdk so let's go to net.microsoft.com download and this page is going to present you the latest version of the net sdk which in my case that will be net 6 and in your case it could be different but one thing to keep in mind is that this course has been designed for net5 not for dotnet 6 or any other future version so even if you have net 6 or another version installed in your machine you have to make sure that you get the net 5 sdk in your box otherwise the project in place that you will be using will generate different code than the one that you're going to see in this course and you're also going to get a few syntax errors so to get the net 5 sdk what you want to do is go to this link all the temp versions and then you want to go into the 5 link over here here at the top of this page you want to look at this table here which lists the links to install.net for the different operating systems so you have to choose the link that corresponds to your operating system in my case i'm running windows and my platform is x64 so i'm going to click in the x64 link and that is going to start unload so this unload could take a few seconds depending on your download speed so let's just give it a few seconds okay so the installer has unloaded i'm going to click on installer i'll click on install and installation starts this could take a few seconds or a few minutes depending on the speed of your machine so again let's just give it a moment okay so the identified sdk has been installed already and i'm going to just close this window and what i'd like to do now is to quickly go ahead and verify the installation just to make sure that it has been installed properly so to do that i'm going to go and open my start menu and then i'm going to look for my terminal my windows terminal and of course depending on your operating system what you can do is just open whichever terminal or shell is available in your box this should work in really any kind of terminal or shell and then all you want to do is just type net and then dash info and this is going to present you with a bunch of details regarding your version of the sdk and your machine like in my case it is showing that i have version 5.0 that 404 of the sdk and then there are many other details here but in the end this shows that that end has installed properly into my machine so that net is ready to go now let's go ahead and load the page to download docker desktop let's go to docs.docker.com getdocker and in this page if you scroll down a little bit you're going to see again that you can pick your operating system so again my operating system will be windows so i click on docker desktop for windows and docker desktop for windows so i'll click on that button and let's give it a few seconds for the download to complete okay so let's go ahead and open the docker desktop installer okay so here it goes we'll just keep these two checks right there no need to change anything i'll just click on ok and that's going to get things started again this may take a while so let's give it a moment to complete okay so installation succeeded i'll click on close another thing about docker is that docker desktop will usually not automatically start in your machine after installation so you do have to start it at least the very first time that you install the tool so to start docker i'll just go to my start menu i'll type docker so here it is you're looking for docker desktop i'll click on it and you should see a new icon show up in the right side bottom right i guess which is starting the docker process okay so this screen shows up i'll click accept all the terms accept notice how docker desktop is starting and then this screen shows up local engine waiting double engine starting give it a second installation has completed it has started i'll click on skip tutorial here and at this point docker is up and running and to verify that docker is up and running properly what i'll do is also type a quick command in the terminal window but i'll open a second terminal just because we want to make sure that it has gotten the chance to read the new environment variable to locate docker so i'm going to close this terminal here close our windows and i'll open a new terminal windows terminal and here what i'll do is just type docker version and if docker is installed it should show up all the details about the current version of docker which in my case is version 20.10.11 for the docker client at least and with that our docker installation is complete so now i'll go ahead and install visual studio code so i'll close this terminal and i'll go into i'll close this i'll go into the browser let's go into aka rms slash bs code and here's the style page for vs code and as usual you're going to be offered the version that corresponds to your operating system so i'm going to click on this big blue button here download for windows stable build and then download starts and this should be pretty fast this is a small starter okay so i'll click on installer accept agreement and then i'll just click all the default options here click install and let's give it a moment to complete okay so then i'll just click on finish and this code is opening up right away i'll maximize this window and as you can see vs code has open up and that completes our installation of initial tools in the next lesson we will go ahead and customize pixel studio code for c-sharp development visual studio code is a lightweight but powerful source code editor that has built-in support for javascript typescript and node.js and has a rich ecosystem of extensions for other languages and runtimes since all the code that you will write across this learning pad will use the c-sharp language and will run using the network time you will need to install the popular c-sharp extension so to start extensions what you want to do is go into your activity bar on the left side this one over here and look for the extensions view via this extensions icon you can click on that one and this is going to show all the available extensions in to the code marketplace of which there are really hundreds of them and then what you want to do is just search for c-sharp and the extension that you want is usually the very first one on the list and is the one that is provided by microsoft and it says c-sharp for visual studio code powered by omnisharp so let's click on that one and this is the extension that adds all the editing support needed for c-sharp including syntax highlighting intellisense find all references and many other features it also adds support for building and debugging.net and asp.net core applications in your box so you have to make sure that you get in this extension in your box to be able to do proper coding with c-sharp so i'll go ahead and click on install and this may just take a few seconds after which you will be ready to start coding in c sharp okay so extension is ready and you're ready to call on c sharp with visual studio code here but let's also go ahead and enable a few optional settings to further improve your coding experience so let's go to let's first close this and let's close that let's go to file preferences settings and here let's type place open race on new line and this is going to filter a few options here and the ones that you want to enable are this one here javascript format place open brace on new line for contour blocks and place of embrace of new line for functions these two settings will help you format your control blocks like if else blocks and your functions so that when you open braces the opening brace automatically goes to the new line so you don't have to use this setting but i find that my code reads much better when i use it the next setting is let me delete this one here delete this is um format on save which is this option right here this first one so i'll click on that one so what this allows is to uh make sure that all your code for whichever file you're working on will be automatically formatted as soon as soon as you save it into your machine right so you save the file and it will get all the formats so that what again we will help you make sure that the code looks way better without you having to do a lot of work across your lines and the last option setting that i will recommend you is this one in file how to save so as the name says what this allows you is to automatically save whichever file you're working on without you having to do anything so as soon as you finish typing your code the file will be automatically saved to your machine so i find that very handy and to make sure that i never forget to save my files so i'm just going to click on auto save and that will enable the setting the last thing that i wanted to show you here is the visual studio code integrated terminal which is the one that you're going to use to type a bunch of commands across this learning pad so let me go ahead and close this settings tab here and to open the terminal what you can do is either go to view terminal or you can go to terminal new terminal or you can use a few shortcuts like for instance in the case of windows you can do ctrl tilde double open terminal or let me kill this you can also use ctrl j and that will also bring up a terminal so of course the shortcut keys will depend on your current operating system now as you can see in this case this has opened a terminal a powershell terminal in my case and that's because that's a default for windows but you can always go ahead and use this drop down on the right side right here you can open up and you can switch to any other terminal that better switch your needs so if you want to use patch you can use git batch here you can use a standard command prompt or you can switch to either even a wound based terminal so it's really up to you what terminal to use in this course we'll be using mostly a powershell because that's that's what i mostly like to use but it's up to you to use whichever terminal fits better your needs in the next couple of lessons we will define the concepts of monoliths and microservices how they compare and which are their pros and cons before diving into microservices and their benefits it is probably worth it to understand first what a monolith is its benefits and the issues it can present to understand what we mean by a monolith let's look at one way we could design our play economy system we start with our desktop and mobile clients like we said they need some sort of backend piece to enable the game experience therefore we introduce a server component likely hosted as a web server somewhere in the internet as we go through the requirements we identify a model that needs to take care of the in-game catalog of items so we introduce a catalog model right away we also perceive the need for a place to store these catalog items which means it is time to introduce a database along with a table to store these items we also identify the need to store the information about our players and in general any user of the system so we bring in a user's model which we place in the same web server next to the catalog model also since we already have a database configured for a web server we decide to add tables for the user's model in that same database next we identify the need to store the set of items that the player has purchased so we bring in an inventory model and same as before we place it next to our other models and add relevant tables to the same database we also need some place to perform the actual purchase process and since this involves both dividing jill from the player and granting items to him we also know we will need to use some sort of transaction for this so we introduce a trading model on the same server and we will let it take advantage of the transactional capabilities of the database finally we will need some way to secure the access to our web server so that only players registered in the system can make use of it so we bring in an authentication and authorization model which we will abbreviate as oddc as with everything else we will place it on the same server and make it use the same database this system that we have just described is what we call a model it and more specifically a modular monolith in this system all of our server-side capabilities are hosted together in the same web server and they all use the same database likely we also have the source code for all the models in a single repository we build all the code base with a single bill process and we deploy everything together let's now look at the pros and cons of a modulate here for the pros and cons of a modblade first the pros convenient for new projects usually when you're just getting started a monolith is the best option since you can put all the source code in one place including all common libraries this lets you iterate quickly for a while tools mostly focus on them most ides are built around the concept of building a single application which aligns pretty well with a monolith there's great code reviews since all the code lives in the same repository it is easy to reuse code across the multiple models of the application it is easier to run locally being a single process it is a straightforward to have the full application running in your box usually with a single command easier to debug and troubleshoot when it's time to fix box there's usually a single place to look for locks to find out what happened you can also start a debugging session in your box to reproduce and fix the issue there's one thing to build a single command is usually enough to build entire codebase locally and if using a continuous integration server a single build pipeline will do the trick there's also one thing to deploy all the application models can be deployed as a unit with a single deployment pipeline there's one thing to test end to end end-to-end verification of application can take place as soon as application has been deployed with no other moving pieces that could impact testing and there's one thing to scale with increased load demands more risk more instances of the web application there's only one app to scale saying when the increased scale is no longer needed there's only one thing to scale down now the cons easily to get complex and to understand since entire code base is in a single place there will be a point where it starts becoming too hard to navigate it and understand the relationships between the different components merging code can be challenging when using things like git and with more and more people contributing to multiple models in a single code base eventually resolving conflicts gets more troublesome and the chances of a bad merge that could impact on related models increases it slows down ids if the devs use an integrated development environment or ide like visual studio the massive number of projects and source code will eventually start slowing down the ide starting with simple things such as opening the work environment long build times the bigger the single code base becomes the more time it takes to build it things like incremental builds can help here but this is something that can easily not be configured properly and regardless it is undesired to have to build code for all the application models when usually you only work on one or two of them slow and infrequent deployments just like building the code takes longer it also takes more time to complete the deployment since there are a lot of components to deploy with every new build not only that teams tend to delay compound deployments to friday night or even weekends due to the lack of confidence on the impact of the changes that go into that deployment remember that with each deployment you are deploying all the application models all the time long testing and stabilization periods once a deployment is complete regardless of what changes in the deployment you still need to test all the scenarios across all of the application models not only this is inefficient but also teams that don't have testing fully automated may need to run manual tests to compensate and run them again for all the application scenarios rolling back is all or nothing books will eventually make their way to deployment and sometimes there's no time to code and deploy the ideal fix in these cases you just want to roll back the previous version however with a monolith you will be forced to roll back the entire application not just the faulty model and once the fix arrives you will need to redeploy the entire thing again with all the associated testing and stabilization no isolation between models the small spock in one of the models that makes the web application crash will take down all the models with it it can be hard to scale this really depends on the kind of app that you're building but if you have some model that needs say a lot of memory and therefore needs to be scaled to multiple instances to not take over all the ramming a single server while all the other models are fine with a small amount of ram most of the time you still need to scale the entire application with all the models to satisfy the ram needs of the first model also it's hard to adopt new tech if you would like to move one or two of the models to the latest version of say the.net platform you are forced to update all the models along with it which significantly increases the time investment and associated risk of moving to a new stack moreover if you need to switch a model to a different programming language or web framework you still need to account for how that change will impact the rest of the models in the next lesson we will start learning about microservices their pros and cons and when it's a good time to start considering them in this lesson we will understand what microservices are how to decompose our previous model lead into microservices the pros and cons of using microservices and when is the right time to start thinking on using them there are multiple definitions of microservices out there but here's one i have synthetized from a few sources and that i think covers the fundamental characteristics of microservices microservices refers to an architectural style that structures an application as a collection of independently deployable services that are modeled around the business domain and are usually owned by a small team so instead of having a single application deployed as a single monolithic unit we break it down into smaller services where each of them is closely aligned to some part of our business domain each of these services can be deployed independently which by the way includes granting each of them their own database which is one of the main challenges of moving to microservices also there's usually only one small and fairly autonomous team behind each microservice let's see how this looks like for the game back and example we talked about in the previous lesson we start again with our client apps which will still interact with some backend pieces to enable the required game experience and just like before we come up with most of the models that we talked about before to address the multiple scenarios however this time each of these models live in their own individual server process or likely a web server process fully isolated from the other ones and with their own lifecycle not only that but also each of these services have their own associated database that has no relationship with the ones from the other services also notice that we decided to group the users and altc models in a single process that we are now calling the identity service but even when these services are now independent they still have ways to collaborate with each other so that for instance when a purchase starts in trading this service will communicate somehow with identity and inventory services in order to achieve the exchange of yield for catalog items this here is what we call the microservices architecture pattern next let's learn about the benefits and drawbacks involved in the microservices architecture these are some of the pros and cons of using microservices let's start with the pros they have a small easy to understand code base since the microservices are now independent the source code for each of them is usually stored in its own git repository this implicitly results in a much smaller repository which is much easier to understand especially for devs new to the code base they are quicker to build the smaller independent codebase per microservice allows for building each service much faster and in parallel both on deck boxes and on ci pipelines they allow for independent faster deployments and rollbacks each service can now be deployed individually as soon as the relevant source code has been built and testing for the domain covered by the service can start right away and is much smaller in scope also if an issue is detected with the deployment it can be rolled back to the previous version without having to roll back any other service they are independently scalable different services can be skilled according to their needs so if there's one service that needs to scale given the amount of ram or cpu it uses it can be scaled independently of the needs of any of the other services there is much better isolation from failures microservices are isolated from each other so that a crashing one service has no impact in the availability of the other services they are designed for continuous delivery since microservices are small usually start fast and are independent from each other they are great candidates for continuous delivery they can be deployed as soon as the code has been built and this can be done safely in an automated way multiple times a day it is easier to top new variety tech different services don't need to use the same versions of their multiple dependencies including the.net runtime even better if one of them needs to be moved to a completely different language or web framework this is much more straightforward to do with a small micro service than with a big model it microservices ground autonomy to teams and lets them work in parallel the natural independence of deployment and isolation of microservices and the fact that they are closely lined to a specific part of the business domain results in the owning teams to have great autonomy around the entire lifecycle of the service some teams might decide to deploy their microservice every night while others will do it every hour or whenever an origin fix needs to be shipped different teams will do what's best for them now the cons it is not easy to find the right set of services how do you know that you have split the app into the right set of services are three microservices enough or 10 perhaps how much granularity these questions are not easy to answer but techniques like domain-driven design and aligning the services to specific pieces of the domain and the teams behind them helps to find the right balance using microservices as the complexity of distributed systems the fact that each service lives in separate silo introduces a lot of complex issues that are non-existent in modulates how to have a service communicate with another one if a model can no longer make a simple method call to the other issues like these are the reason for this curse the shared code moves to separate libraries any piece of code that needs to be shared across two or more microservices now needs to be either duplicated in each service which is not ideal or moved to a separate library and likely sharpie and nougat packages this is technically good since it forces the owners of the share code to have a good way to test the shared code independently but on the flip side things are no longer as easy as adding a new shared class or method to any of the services codebase also you may end up with dozens of shared libraries that may need to collaborate and have the right set of dependencies there is no good tooling for distributed apps ides are usually focused on a single app not uploading several services together this means that devs will usually work on one service at a time and will need to figure out ways for their code to interact with other services in their dev environment where needed releasing features across services is hard simple things like adding a new attribute to say a user record and have it been used across the entire system can involve touching multiple services in a very coordinated fashion even worse updating or removing attributes from data classes is extremely painful and usually avoided as much as possible it is hard to troubleshoot issues across services when a customer reports an issue with the system or application where you will start looking with features potentially distributed across dozens of microservices you are forced to have a very good story around tracing issues across services to be able to quickly find out the root cause and address it you can't use transactions across services since each service has its own database atomic transactions that impact multiple tables are usually out of the question how to ensure a purchase operation will both debit jill from the user and granted the relevant items when one of the involved services could unexpectedly fail in the middle of the purchase process a few new patterns and techniques need to be introduced to properly handle these concerns finally it raises the required skill set for the team with each team fully owning the service and since not all services will be built similarly each team now needs to learn not just how to code features for the service but also how to build it deploy it test it in isolation diagnose it roll it back etcetera many times this also involves building a ton of automation and shared infrastructure to ensure teams can remain agile building features and not have to worry too much about all the other aspects this requires a lot of investment let's close this lesson by understanding when you should start considering microservices you should keep in mind that it is perfectly fine to start with a monolith and only later move to microservices architecture your business domain and the set of requirements for your system might not be fully flushed out by the time you need to start designing and building the system therefore jumping into building multiple microservices from the start could not only significantly slow down the small starter team at a time when quick proof of concepts are desired but also you may end up building the wrong set of microservices with additional cost of having to restructure them later the heavy investments on shared infrastructure and automation will only make sense as the boundaries are clearly defined and the team has grown in size you should start looking at microservices when the code base size is more than what a small team can maintain the different teams can move fast anymore due to the amount of share code the bills have become too slow due to the large code base or the time to market is compromised due to infrequent deployments and loan verification times in the end microservices are all about team autonomy anytime you notice multiple teams no longer being able to deliver features in an agile way due to the drawbacks of the monolithic architecture you know that your teams have lost their autonomy and they could potentially greatly benefit from using microservices instead in the next model we will get our hands dirty by building our first microservice in this model we will build our first microservice from scratch this will give you the foundations and tools you will need to create microservices with the.net platform by the end of this model you will have a solid understanding of the following how to create a microservice from scratch via the.net cli and visual studio code how to define the microservice rest api with the most common operations and what are and how to define the data transfer objects to establish the contract between our service and the service clients in this lesson we will create our first microservice the catalog microservice using the.net cli and visual studio code to create our microservice project we will take advantage of the.net command line interface also known as netcli which comes installed with the net sdk so first thing i'll do is create the folder where i'm going to store my projects so to do that i'll go to terminal new terminal and then i'll switch to my d drive and to my products folder and i'll create a folder called play that catalog so everything related to the play that catalog uh catalog microservice will be stored in that location so i'll open that folder and visuals to the code now by going to file open folder and then i'll look for that location here so this opens a workspace in that location so being here what i'd like to do is create yet another folder to store all the source files for the for the microservice so i'll go on the left side here i'll go and click on new folder and then i'll type src so src is going to be the folder that stores all the files related to compile duplication i'll expand this and then i'll right click on src and select open in integrated terminal so this opens a terminal exactly the location where we're going to create the project files to actually generate the files what we can do is type net new and at this point you can actually pick from a bunch of different templates for creating.net projects but the one that's most useful for microservices is usually the web api kind of project so we'll all type web api and the name we're going to give it is that lay.catalog.service hit enter and this is going to go ahead and generate all the files that we need for the project which at this point you can see on the left side also notice that there's a small warning about the asp.net core https development certificate which we'll take a look in a moment now if by any chance you have multiple versions of the net sdk installed in your machine and you're not sure that that n5 is your default version please add the framework argument to the net new command and specify the value of net 5.0 for dot n5 that will make sure that you are using the asp.net core 5 templates when creating projects which will produce the same files that you will see in these and in future lessons now let's go quickly across the files that just got generated and see what they are meant to be used for so the first one is going to be alter i'd actually just close this terminal the first one is going to be the cs profile which is what we call the project file so this is the file that defines how the project is going to be built and what version of the dotnet runtime is going to be targeted in this case it's going to be.net 5. the next one is program cs which is what we call the main entry point of the application but also notice that as soon as we open our first sharp file visual studio code is going to prompt us to add a few regard assets to the project and we'll say yes so this will create a vs code folder on the left side with a couple of files that are needed to build and debug the application now like i said back in program cs this is the main entry point so this defines how we're going to start the the host for our application next file is going to be startup.cs this defines how we're going to uh register the services are going to be used across application and what we call also the request pipeline for espnetcore the next one i'd like to show you is the controllers folder this is where we store all the application controllers to handle the requests that are going to come into the application and this is a campaign this is a campaign with uh right now by a model that's called the weather forecast for the simple sample model that has been set up in this template next file is a launch settings.json this one defines a few things but the most important one is the application url which defines which is the address or the addresses where our microservice is going to be running so in this case it is going to be available in https localhost 5001 and on https sorry http localhost 5000. finally like i said this is the code generated a couple of files over here that's a json which defines how we're going to build the code from visual studio code and launch application that defines how to start up how to actually kick off the execution of the application in visual studio code okay now i'll close this and it's time to actually build this project to make sure we'll build and run it to make sure that it's running properly so in order to do that what i'll do is i'll go back to the terminal and you can do that by going to view terminal which by the way you can also do via the control j shortcut faster that way and then i'll switch to our play.catalog that service directory play that catalog service and then we'll be in there and what you can do there's actually a couple of ways that you can build this project so you can either do net build like i'll do now that will go ahead and build the entire project should be pretty fast and the other way to do this is via visual studio codes menus you can go to terminal realm build task and then you select build and that will also go ahead and build the project now this second way is the way that you will most likely be using a while being exhausted to your code and to make this actually a bit faster what you can do is add a little bit of a couple of lines into the task.json file so let me minimize this a bit so go to that json and here under the under the build section what you can do is just add one little group here let's add it it's called group and then we're going to go for kind build is evil true i'll save this and after doing that what you notice is that when you go to terminal and you say run build task it will build it right away as opposed to opening yet another menu to do the build at this point you can also do uh you can also use the ctrl shift b shortcut like i'll do now to kick off the build without having to go through any menus which is pretty handy okay now that we know how to build the project and i'll actually just close this how do we how do we run it so there's a couple of ways to do that too so i'll actually switch in this drop down i'll go back to our terminal the partial terminal and the way to run the this microservice this microservice project is by just typing.net run so that may build the project depending on the current status but after that it will go ahead and run it as you can see and it reports the current status uh the the the address where the where the host is listening the addresses in this case 5001 5000 in localhost and how to actually turn turn down the application if needed by ctrl c that's one way and i'll actually do a control c to stop it the other way to do it is by going to the to the wrong view on the left side and here you can click on this on this icon here says start debugging it will actually start a debugging session of the project as opposed to just running it so i'll click on it okay and this will open a browser window as you can see here for our project now if you see this this kind of an error stating that your connection isn't private this is totally normal so this just means that the development certificate for the for the web host has not been installed yet so in order to address this let's actually go back let's close this and stop it and what we have to do is just install the certificate i mean trust the certificate in our machine so i'll go to terminal switch back to the partial terminal here what i'll do is use the net dev search tool you have to type https trust hit enter and this is going to pop up this little warning here which is totally fine and say yes and that adds a certificate into your thruster rule certificates stored in your machine so after doing that i'll go ahead and instead of clicking on this i'll just hit f5 which is a shortcut for start debugging so i'll hit f5 so that obviously browser came and as you can see there's no errors anymore and yes it is not showing anything uh that that's because there's nothing really happening in the in the root of the website so if you actually want to see something you can do slash swagger and this opens the swagger page so i got ui page so this is the page where you can start exploring the different methods exposed by your web api or your res api in this case we have not really coded much the only thing that you're seeing here is the default stuff that's coming with the template so we'll not pay too much attention into it but later on we'll start using this page heavily to start working with our microservice i'll close this and i'll stop the server so that's it for this lesson and in the next lesson we will define the rest api for our catalog microservice in this lesson we will define the res api for our catalog microservice the res api defines the operations exposed by the microservice since the catalog microservice owns the items that players will be able to purchase here are the operations that it should support get items which retrieves all the items currently stored in the service get item by id which retrieves the details of a specific item post item which creates an item in the service put item which updates a specific item and delete item which deletes the specified item as part of the definition of the res api we also need to define the relevant data transfer objects so what is a data transfer object a data transfer object also known as dto is an object that carries data between processes for example let's go back to our client and the catalog service when the client needs to retrieve the details for a specific item it will send a get request to the service with the item id and the service will in turn return the item details this payload returned by the service is what we call the dto the dto represents the contract between the microservice and the client we'll define this contract has significant implications imagine what would happen if we decide to rename the price to item price our clients would break and they would need to get updated right away to ensure no disruption to our customers as a general rule you need to think carefully about each of your details to ensure you minimize the need to update them later as much as possible it's time to define the res api for catalog microservice we'll start by deleting a few files that were created by the template that we will not be using across this microservice which are the weather forces controller i'll delete this and the weather forecast class over here now the first thing that we're going to do is declare the details for our service now we will use record types for dtos as opposed to classes basically because they are simpler to declare they provide value based equality which means that when comparing two of the items then we will consider equal if all their properties have the same value which is not the case with classes they are immutable by default meaning that modifications after creation are not allowed and they have a built in to a string overwrite that shows the names and values of all the record properties so to create the dtos file you can right click on play catalog service right here say a new file and then let's name it dtos.cs in this file first thing we're going to do is just declare a namespace so namespace should have the name of the folder to start with so play catalog service and then we will append dtos now let's declare our first cto this is going to be the dto that is going to be used to return information from our get operations so public record item dto and the first thing that is going to have is an id it's going to be of type good and good is a type that is going to need a namespace import so to import namespace i'm going to use a light bulb here and i'll select using system so that imports the namespace and then we're going to declare a name a description a price and a created date okay now the next cto is going to be used for the creation of our items so let's say public record is going to be named create item dto this cto does not need an id or a created date because both of them are going to be automatically generated within the service so they don't need to be provided by the client so we'll specify a name a description and a price finally we're going to declare a dto for updating an item so pull the record update item dto and this is actually going to have the same members as create item dto so i'm going to copy those and uh it happens to be that right now they have they need the same members but it could be in the future that they need different different properties so a good convention is to keep them separate even if they have the same properties to start with in the next lesson we will add a controller to define our res api operations in order to add our api operations we will need to introduce a controller specifically a web api controller the controller groups the set of actions that can handle the api requests including the routes authorization and a series of other rules usually needed in rest apis so to start let's go to our controllers folder here right click new file and the name that we're going to get to this controller is items controller since this is going to be the controller that's going to be managing our catalog items so let's go ahead and collapse our navigation pane so that we have more space for looking at the code let's start by defining a namespace the namespace catalog service controllers okay and now let's define our class it's going to be items controller and so each of your web api controllers should derive from controller base and i'm going to import the missing space by doing control dot using microsoft switch core mvc so you always want to derive from controller base not from controller but controller base because this provides many properties and methods useful when handling http requests like the battle requests not found and created attacking methods which we'll be using in these and in future lessons now you should always also add to each of your controllers the api controller attribute so api controller this attribute enables a series of features that improve your sapi developer experience like for instance having model validation errors automatically return a 400 request error or how to bind incoming requests into our method parameters the other attribute you want to add here is the route attribute this one specifies the url pattern that this controller will map to for instance if we use items here that means that this controller will handle the rewards that start with slash items so for instance if we get let's say i'll just add a little comment here so we have localhost 5001 and if somebody navigates into items that means that since the route specifies items here that means that items controller is the controller that's going to handle that specific route okay so i'll remove this and you can also use route for the different uh operations that we're going to define in this controller you can specify your own routes but for now uh this is going to be our root route for all the the operations in this controller now since in this lesson we would like to focus on the rest api part of microservice we will not be interacting with the real database just yet we will use an in-memory list of items that our api variations will interact with and in a future lesson we will introduce a proper repository class that will take care of interacting with our database so let's start by defining this a static list so i'll declare probably static read only we'll make this list read only because we will only allow to construct it i mean to create it or instantiate it during a controlled construction time and after that there will be no need to modify the instance of this list so it's going to be list of item dto because uh uh this is going to be the list that we're going to be returning when somebody requests the items from our rest api so we want to specify the contract that we already find for our items here so item dto and then it's going to be named items equals new and so let's see we're missing some more next spaces here okay so i'll do ctrl dot again system collection is generic and we also need our play catalog service dtos namespace so let's find our first item here so i'll just define it in line here so new item dto for the id we'll just generate a generate a random good so a new good mainly another nice space import yup and for the name let's name this one potion the description is going to be restores a small amount of hp the price is going to be let's say five and for the created date let's just do the time of set that utc now okay it's going to be the the current time in utc time so let's add i'll just copy this to add two more items the second one is going to be let's say an antidote and so the antidote cures poison price is going to be let's say seven credit date is utc now and the last item is going to be let's say [Music] a brown sword and it deals a small amount of damage it's going to be a big price here let's say 20 and yeah utc now column save okay also notice that we're using a static list here so we do this so that the list does not get recreated every time somebody invokes one of our res api methods right otherwise the list will be recreated every single time that a method is invoked which we don't want so now let's define our first operation this is going to be the operation that's invoked anytime somebody tries to get all the items that we have in the rest api so we're going to say public innumerable off item dto get okay and so yes we're returning a list of identito now each of your api operations should be a marked with the correct http verb right since this is going to be responding to our the get verb we should mark this with the http get attribute and then for for this method really is super simple we only need to return the current list of items right so we just return items so that's our first get operation the next one is going to allow us to return one one specific item so we'll name it public item dto get by id okay and then we're receiving the the specific id as a good and just like we did before we need to decorate this with the http get attribute but here we also need to specify uh what part of the of the route that the user specifies is going to map to that id so in this case we do that by specifying id here okay so that means that uh if somebody comes with and i'll put it so here so somebody go does it get there's a little comment here does it get into our items route and then they specify some id like one two three four five uh that one two three four five is one is is captured as the id in the http get route and that's mapped into the id parameter over here okay so the route would look more like in a more generic case it's going to be slash items slash id and so to do this the only thing we have to do is just find the correct item in our list so we'll say bar item equals items where and for this i'll need ctrl dot system.link so for each item we will do a item.id should match the id that we got in the parameter and then we will say okay so let's find the only the only item that should match with that id get that one otherwise i mean with single default we can say either get the item or just return null in this case and then we return that item okay so that's what we need uh for our get routes so let's try it out to see how that that goes so i'll hit f5 my keyboard to start a web server that opens the browser and let's now navigate to our swagger page so slash swagger and here you can see that we have our two first api operations defined items and items by id and we also have the the schema of our itunes dto showing up here right so if you expand this one we can see the shape of our item video right there so if you expand the items route you can see a little example here of what it would return and expected a return for a successful case and then if you want to try it out just have to click on try it out then you click on execute and here you can see the actual the request url that was invoked into our api slash items and then you can see the response body here along with the status code 200 and the response body has the three items that we have in our static list so that's working fine and let's say that we want to try the other a operation where we have to specify an id so i'll just copy the id of one of these i'll collapse this for a moment i'll expand the other so this one expects an id this parameter so i'll do try it out i'll paste the id here and then i'll click on execute and just before it it will go ahead and use the items a route but it will append the id of the item and as you can see we got a 200 okay and we got in the body we got the actual uh the body of the of the item that it was retreat okay so that's working fine so let's now add a method for creating an item so minimize this stop debugging and then i'll close the terminal okay so to create items we're going to be using the post http verb and let's create a method for that so it's going to be public action result now the action result type uh so this one allows us to return a return a type that represents one of the several http status codes like 200 okay or 400 requests but it also allows us to return a more specific type like a dto type if we need to so we can return different types depending on what we have available so let's see how we're going to be using this um so action retooled off type item dto and it's going to be named let's just name it post for now and then here is where we're going to receive our create idm dto contract right so that in that way we enforce that uh whoever calls this this api has to follow our contract for creating items so create item dto and this one has to use also the correct http verb it's going to be http post and then for creating an item we will just create it in line here so i'll just say var item equals new item dto and we'll assign a random id here just like we did with the with the list you do it and then we will say for the name we'll say create ideo.name for the description that description for the price created you that price and for the day for the great date again daytime offset you'd see now so that's the item and now now that we got it we will just say items dot add to add the item to our to our static list finally we're going to return the type created action uh which is a is derived from action result so this so this is going to be used to say hey so the item has been created and you can find it at the following route uh which route is is going to be well is the route with the name so name of get by id so this means that uh the caller will be able to find i mean we're going to produce a heater in the response that includes the exact route of the item as provided by the get id operation over there we will also provide the id of the created item as an anonymous type here is going to be id equals item.id and lastly the actual the actual body of the response which is the entire item right so it's ready i'll do f5 so we can try that out see how that goes okay back here i'll just close this one so back into the previous tab i'll do f5 as you can see now we have the the post operation listed here and the create item dto listed at the bottom so i'll go for post i'll expand this and to try it out i'll do try it out uh so here's where we can create a new item right so let's let's figure out some new item to create here let's say we're going to create a high potion and so this one is going to restore a medium restore restores a medium amount of hp and the price is going to be let's say nine okay and so now i'll do execute as you can see it invokes uh the same route but in this case it was with a with a post verb post and uh yeah so we got 201 which means created a created route create or created at here's a response body so the entire created item including the auto generated id over here and here you can see the heaters includes the location the location of the just created item so if i wanted i can grab this id and i can collapse let's call exposed and then expand get inside id try it out and i can paste that id here and i should be able to find that just created item as you can see or here's the high potion so post is working just fine so now let's say that we want to update an item so that's where we need to introduce the put the put operation so let's go back to our piece of studio code stop this and close terminal and let's declare a method to update items so for this term for this one i'm going to declare public action result and i'll be using i action result because in this case we don't really need a specific type for the return we will just return this one called no content meaning uh that's that's what um uh you usually do for a put operation you don't want to return anybody you just say hey uh yeah i did my job but there's nothing to return so it's going to be named put so we want to receive the id of the item to update and we will use the update item dto contract to receive the new the new payload or the new information for this existing item it's updated in dto and we also have to specify the proper verb so http put and just like we did with the get by id we have specify what part of the route is going to be used for the id parameter so just like before it's going to be id okay so once again when somebody comes with a something similar with get items by id somebody comes with uh not get but put items slash id and somebody then this is the operation that's going to be honoring that route so how do we implement this so the first thing that we want uh that we want to do is probably find the item that we're going to be updating so what i'll do is i'll just say existing item listing item is going to be done under items list uh items list where item uh item.id is the id that we distributed the parameter and then again singular default right so if you have it i will find it right there now we found the item we're going to update it and to update it we're actually going to do at this point is just clone it into a new item with the updated values so we will say updated item is going to be the existing item with the name that is going to be update item update item dto dot name description date item dto that description [Music] and price updated in dto price okay so that creates a clone of the existing item and the in into updated item and that's the one that we're going to be updating into the list okay so now we'll do is we're going to find the place in the list that uh that has the item that we need to update so to do that we're going to say so the index of that item is going to be in the list find index okay so it's going to be existing item.id equals id okay so that finds the index on that list where the item is and then now that we have the index we're going to say items index equals updated item replaces that in the list and then like i said we will just return no content there's nothing to return okay so let's try this out so i'll do f5 once again start the web host and close this page and then i'll just refresh our swagger ui page and as you can see now we have our put operation here at the bottom and all the way to the bottom we also have our update item dto specified so i'll expand put this is going to require first the id of the item to update so to get an id i'll actually execute our get items route so i'll try it out execute and let's say we're going to update our antidote so i'll copy the id of the antidote collapse this and then back in the input i'll say try it out i'll put the id here and then let's grab a few of the properties of the antidote we don't have to start from scratch there collapse this and then i'll place those items here remove this comma and then let's say we want to update just the price and we'll say that the price the antidote is going to be let's say nine and i'll go ahead and do execute and as you can see in this time it invokes the api with a port with the put verb into this request url that includes the id of the item we get a 204 result meaning no content so as you can see there's nothing being returned here but the item was certainly updated and we can confirm that by grabbing the id of the item once again and going to our get items by id route we can try it out paste it there i'll execute and then you can see now we have the antidote with price nine so the update operation succeeded so finally let's add the operation to delete an item so let's minimize this once again stop and close and before adding our delete route just for completeness let me do let me add the comment here for our http post route which i did indeed didn't do uh this the post route is going to as we as we saw responds to the post verb and the browser is going to be like just items right so jose we have that comment over there now for the delete route uh is we're going to be using uh a method that is also be returning a action result just like in the boot case because we're not we're going to be returning no content here also and it's going to be delete and we're going to receive the only thing that we need to receive here is the id of the item to delete and we also have to respond to the http delete verb and again just with the we put we have to specify which part of the route we're going to be using for the id of the item to delete so that's going to be a id once again and here uh just like we did with update we need to find the index of the item to delete so i'll copy that line from put copy that into here okay and so once we found the index of the item to delete we're going to say okay so from the list remove add and we'll say index so that removes the item at that index location and then we will just return no content so again for completeness let's add a little comment here so when somebody comes with a delete verb and says lash items and then slash some id this is the method that's going to be honoring that that deletion so to try it out again i'll do f5 okay so back in swagger ui i'll refresh the page and as you can see now we have our delete route a little operation showing up here and so i'll expand that so we need an id to delete so let's actually execute our get items route try it out execute so we can pick something to delete let's actually delete this antidote once again so let's copy the id of the antidote and so i'll go back to delete try it out i'll paste that id and then i'll hit execute and as you can see now we're using the delete verve invoking the api we delete here's a url of the of the item that needs to be deleted and we got a 204 no content so as you can see there's nothing returned but the item should have been deleted so if i go i'll collapse this and i'll go back again to our to our a get items route i'll to execute again and as you can see the item the antidote item has been removed it's not here so delete succeeded so yes rest api seems to be working just fine um however you can try querying for an item that uh that does not exist and exit on an existing item or perhaps creating an item that does not have a name uh what will happen in that case so we'll need to do something about those those situations uh in the next lesson we will see how to properly handle these kinds of invalid inputs let's try a few of the unexpected scenarios that our microservice dress api could face from time to time so i have our catalog project open here and i'll just do a five to start a web server and go to our swagger ui page so here we are in the browser i'll go to [Music] swagger and let's start by getting the full list of items as we have them right now so open our get items operation try it out click on execute and here are the three items that we have available right now so let's say i want to query for one of these items the potion so i'll copy the idea of the potion i'll close this and then i'll actually go to our get is by id operation okay so i'll do try it out i'll paste id here but i'll actually going to i'm going to flip a one of the characters here i'll flip this one to two so this is an on existing item we don't have that available and i click on execute see what we get so what we're getting is a 204 result right which is not expected when when an item is not found in the rest api the expectation is that you would return a 404 status code or not found so let's see what's actually happening back in visual studio code see where we're getting this so i'll put a breakpoint in over here in organic by the operation and then i'll go back to swagger i'll try this again so i'll hit execute and here we are this is studio code so we try to find the item and of course the item is two we cannot find it okay so what can we do about this let's see i'll just stop debugging here close terminal and so really the fix is fairly straightforward here um what we would like to do is just check that if the item is null we will go ahead and return not the item but would like to return the not found a action result however of course uh intelligence is complaining here because uh we not found does not convert into item dto here right so here's where action result becomes super useful now we can say action result of item dto and that gives us the ability to return it in the either the item over here or the not found result over here in this case so as you can see we can return more than one type of result depending on the current situation so let's try that out i'll hit 5 once again i'll remove this breakpoint first and then i'll hit a 5. okay so here we are again i'll just copy this id and refresh the entire page should still be and not found items so get items by id i click on try it out i'll paste that id here and i'll hit on execute see what we get so as expected this time we get a photo for a result saying not found so this is the correct status code for an item that cannot be found in the in the rest api and likely we're going to have the same issue with our put api right so let's see exactly which apis will be impacted so not post but put is going to be impacted because it needs to find the item and likely the delete operation could also be impacted because it needs to again find the item before it can delete it so let's start by fixing put [Music] it's going to be pretty similar basically if existing item is no we will say not bound okay so that will do it for put and then in the case of delete what we're going to do is just that if index is less than zero so basically a negative number it means that we cannot find the index of the item therefore we have to say return not found okay so i should do it i'll hit f5 and see what we get i'll close this and and i will um yeah i'll copy that's this id one existing id once again and i'll try to do a put operation now so i'll try it out i'll put this id here and uh i'll put just something here for the for the body so some item some item description and price too so just to try it out and so i'll go ahead and say execute and as expected now we can get a 404 on that case not found i'll take that id once again and let's try out our delete operation so let's try to delete that an existing item see what happens so yeah as expected delete is also returning a 404 so we can now say that we're probably handling the case of not finding items in in our different res api operations now let's try something actually different so what happens if we try to create an item with some missing item properties right so let me collapse this and collect this and then let's go to post okay so i'll try to post an item uh let's say without a name we shouldn't be allowed really and let's say that this was really for our high potion which the description would be restores a medium amount of hp and that price was five right perhaps seven and so let's try to create an item with no name so go ahead and hit execute go down and 201 meaning create an action so it actually got created but look at this the name is nu and if we try to query for that item with this this id so let's do get by id try to query for it as you can see the item is is now in our collection and is with a new name and not only that let's see what happens if we try to create it with a negative number right so not seven but let's say minus seven what happened in that case uh so let's do execute and again it got created to 201 and then now we have this order id and so now this item actually has a a null name and a negative price so this is really bad so what what can we do about this situation um let's go back to visual studio code just open close and then i'll expand our navigation pane again so what we can do is actually do some model validation right so back to the dtos we need to introduce a couple of attributes to properly validate the inputs here and the details that we would care about in this case are both in the create and the update details so what we can do is let's say for the case of the name if the name is always required what we can say is just add this attribute here called required which might require a namespace import system company model data annotations import and that makes it so that name will always be required any time somebody uses this create iron detail okay and i'll also add it for our uh name name property in the updated identity and then also i'll do we can do something about the price so in the case of the price let's say that well let's add an attribute here and let's say that what we want to enforce is that the price should always be let's say between 0 and 1000g right let's say but we actually want to allow free items so they can be zero but definitely not negative and only up to a thousand so we can do is use a range attribute here and we can say here the minimum value which is going to be zero and the maximum value let's say it's going to be a thousand here okay so that makes it so that anytime somebody specifies a price here it has to be in this range that implicitly also makes sure that uh it cannot be null right but however i mean since if this is a value type decimal really this value can never meet dual so worst case it will be zero but with this we ensure that it has to be between zero and a thousand i'll do the same thing for our item detail hit save and now let's try it again so i'll hit a five okay back here and i'll go ahead and i'll just copy this and i'll refresh our page so let's go ahead and try to do a post try it out and so let's start first with no name so i'll say the same price is still positive but we don't have a name and let's try to execute this and see what happens so as you can see this time we do get a 400 but request error which is expected in this case and we do have a the proper validation message coming out of the the errors these errors array that is available now so one or more validation error secured status 400 and the name field is required so that's great and furthermore if we still want to use that negative number so i'll do -7 hit execute see now both validations have been performed so the name is name field is required and the field price must be between 0 and 1 000. you can also try using invalid input for our put api operation now and you should get similar validation errors in the next model we will learn about the repository pattern and we will stand up a proper database to store our catalog items in this model we will update our catalog microservice to be able to store and query for items that live outside of the service and into a proper database by the end of this model you will have a solid understanding of the following what is and how to use the repository pattern to store and query data how to use a mongodb database as the underlying data store of catalog items how to use docker to run infrastructure services like mongodb server what is and how to use the dependence injection technique for proper decoupling of dependencies and how to use the net configuration system to specify settings that could change across environments in this lesson we will learn about the repository pattern and how to implement a repository to manage the catalog service items in a mongodb database so what is a repository a repository is an abstraction between the data layer and the business layer of an application to understand why you may want to use a repository let's say that today we have the application logic of our service talking directly to our mongodb database however a few months or years from now requirements change and we need to switch to a different database provider given the way that things have been set up we would likely need to rewrite a good chunk of our application logic in order to talk to the new database which is pretty bad instead what we can do is introduce a repository this repository is the only one that knows how to talk initially to our mongodb database and is the only one that our application logic will interface with then if we ever get the requirement to move to another database the only thing that we would need to change is our repository but the application logic stays the same so the repository pattern is important because it decouples the application logic from the data layer and minimizes duplicate data access logic across our service we will be using mongodb as our database of choice for all the microservices in this course mongodb is a document-oriented non-sql database which stores data in a json-like documents with dynamic schema we will prefer a non-sql solution as opposed to a relational database for microservices because we won't need relationships across the data because each microservice manages its own database we don't need acid guarantees where acid stands for atomicity consistency isolation and durability which are properties of database transactions that we don't need in our services we won't need to write complex queries since most of our service queries will be able to find everything they need in a single document type and we need low latency high availability and high scalability which are classic features of nosql databases let's go ahead and implement our items repository before implementing a repository we will need to decide which is going to be the class that represents the objects that will be managed by the repository and that will make their way into our database the classes we use for this should not be confused with our details because we want to have the freedom of updating how we store the items in the database at any given point regardless of the contract that we'll need to honor with our service clients we will then give the name of entities to the classes that are repository use so let's start by adding a directory to store these entities so right click on play catalog service let's add a new folder let's call this one entities and inside entities let's add a new file and our main entity here is going to be the catalog items so let's just call this one item.cs and here let's go ahead and delete our namespace it's going to be namespace entities and now let's declare the class all right so our item entity is going to have a good which is going to be the id and let me ctrl dot to import the system a space it's going to need a name it also needs a description and we also need the price and finally we are going to need a daytime offset that's going to be the created date okay so now it's time to actually add a repository but before doing that we're going to need a nuget package the mongodb driver nuget package because this is the one that's going to allow us to actually interface with the bongodb database so to do that i'm going to do ctrl j in my keyboard to open the terminal and i'm going to switch to the directory where we have the catalog service so that would be a catalog service so then i'll just do net add package mongodb.driver so this will bring in a bunch of uh libraries that we're going to be using um for interacting with bungryb so and you can configure the the package was added if you click on play catalog service csprock you'll see that we have the new library right here okay so now uh let me just close this terminal and now we can actually create a directory for our repositories so i right click play catalog service new folder repositories and in this folder i'll create a new file uh again since this repository is going to be managing our catalog items i'll name it items repository that's yes and at this point i'll just close this navigation pane so we get more space let's add a namespace it's going to be repositories and the name like we said public class items repository okay in order to be able to interact with mongodb we're going to need a few class level variables here the first thing that we're going to define is actually a constant we're going to name it collection name collection name which is going to be the value is going to be just items so the collection name represents the group a a collection represents a group of objects in mongodb similar to us in a relational database you will have a table in mongodb you have a collection okay so the collection that we're going to store all these items in mongodb is going to be named items in our case now we're going to define the variable that's going to hold the actual instance of this mongodb collection so let's name this one read only i collection of item db collection okay so i'm i'm going to need to start importing spaces here so ctrl dot to import mongodb the driver and ctrl dot to import play catalog service entities like i said dvd collection is the object that represents our actual mongodb collection we'll add one more class level viral here to represent the the the filter builder that we're going to be using to build the filters to query for items in the mongodb so let's declare a filter definition builder of type item let's name it filter builder and we can get that from builders of item dot filter now that we have that we can go ahead and declare the constructor of this a repository so public items repository and here what we want to get is to actually construct the instance for db collection but before we can do that we have to start by using the client class which is the one that you can use to actually connect to the database here's where you declare how you're going to connect to mongodb so we're going to say client equals new client and here we can specify the connection string to connect to mongodb for now we'll just declare this connection string right here in plain text but later on we'll move this connection into a more to a more suitable place so it's going to be mongodb localhost 27 0 17. also in a future lesson we will learn how to actually stand up that mongodb server so that it actually lives in localhost 27017. now we're going to declare the object that represents the database the actual database where these catal guides are going to live so database equals mongol client get database and then the name that we're going to give to this database since this is the catalog microservice the name is going to be just catalog finally we can give get an instance for db collection and we can do that by doing database that get collection of item and then we give it the collection name that we have already declared okay we'll be using this divi collection object for a few a few operations in a moment now for the repository public methods we will be using the asynchronous programming model this will avoid performance bottlenecks and enhance the overall responsiveness of our service to take advantage of this model all fermenters will become asynchronous by returning asynctask and by using the await keyword anytime they interact with the database we will also use the async suffix on all the methods to surface the fact that the methods are asynchronous okay so the first method that we're going to implement is the one that's going to be able to return all the items in the database so let's name this one fully async task of i read only collection of item get all async okay so i'm using a i'm using a namespace here so like i said we need to return task to make this method async and i'm also using i read only collection here because really the expectation from the the point of view of the consumer is that we're going to provide a collection of items that the the consumer should not need to modify so this is a collection that should only be read right so this is a good api pattern to follow how with this collection of items so basically we can do return await tv collection then we can do find define operation and here since we are not going to really provide any filter because we want all the items we can just say filter builder dot empty delete sync to convert that list into an asynchronous list and then yeah that will give us all the items in the database okay so let's now declare a method that we can use to get one specific item from the database so i'm going to declare public async again task of item in this case and we'll name this method get async it's going to receive a good it's going to be the id of the item and i'm going to import the system in space for this okay let's scroll down a bit and then to be able to query for this item we need to create a filter so i'm going to declare a filter definition of type item let's name it filter and then we're going to use the filter builder to say that we want to build an equality-based filter we're going to receive this this entity object where the entity.id should match the id of the of the parameter that we just received okay so that's how you can build a filter to find a one of the items based on id then we can just say return await db collection find that we provide the filter and we'll say we want to get the first item that we find so we're going to use first or default async in this case so that will find the first item in that collection that matches that filter let's now add a method to be able to create an item into the database so to do that we can define fully case in task create async receive our item that we're calling it an entity here and the first thing we're going to do is a quick check uh to make sure that the that receive parameter is not null so if entity is no we're just going to run a section [Music] argument exception and we're going to name and give the name of our entity parameter okay and then to create the actual item is as easy as saying um await the collection insert one async and then we provide right so that will go ahead and create the item into the database the next method we're going to implement is i want to update an item an existing item into the database so to do that i'm going to declare public async task of data is sync notice that both create and update are not returning really anything so the citation is that we just insert or update the item but we're not going to return anything back to the client um here we're going to receive the item to update let's call it entity that's the item to update all right and just like we did with create let's do a quick check make sure that we're not getting an old value here and now we're going to build our again our first definition to be able to find that item and i'm going to copy the one from get async just because it's a very similar filter the only difference here is going to be that we're going to rename this this parameter here to existing entity just to not confuse with the the entity that we're going to use to find the id so we're going to say we need to find the existing entity whose id matches the entity that we received that id so that's a filter to find the existing item and then we can go ahead and say weight the collection dot replace one async we pass the filter and we pass the entity that has to replace the existing item found by that filter and finally let's implement the mentor to delete an item from the database so we're going to say public acing task it's going to be remove async you find the id of the item to to delete again we're going to use a filter very similar to the one we use for get async so i'm going to copy that one once again so copy that that finds the item and then we can say weight db collection delete one async and we pass the filter yep that should go ahead and delete the item from the database and with that our itunes repository is ready so in the next lesson we will integrate it with our existing isis controller so that it can start creating items from mongodb it is time to integrate our new items repository with our existing items controller but before we can do that we are going to need a wait a way to translate our new item entities into our existing item dto specifically for the purposes of returning these ctos in our get operations in the rest api so there's a few ways to do this but one simple way that we can achieve this is by introducing an extension method so let's see how to do this we're going to right click on play catalog service and we're going to add a new file that we're going to name extensions that's cs let's add any space here namespace play catalog service and here we're going to declare a class that we're going to name those extensions and in this one we declare a public static method that returns itdto and this is because all extension methods should be should be static and we're going to name it as dto so this method is going to receive a current instance of an item entity okay and then let's import namespace control dot play catalog service ctos and play catalog service entities okay so the purpose is to just turn the item entity into the item dto and to do that we just have to do return new item dto and we're going to provide here the different parameters right everything comes from the entity so item id item that name item description item the price and item that created date okay so as you can see it's a very simple method that just turns an item into an identity we'll see how we use this in our controller so now let's open up that controller so controllers items controller and i'm going to close the navigation pane once again to have more space and the first thing that we're going to do is to actually get rid of this list we don't need it anymore and we're going to replace it with a variable for our repository so it's going to be private again read only because we don't want it to be modified after construction items repository and we're just going to say new so it's going to get constructed when the controller gets constructed i'm going to import the writing space here so let's start using this item repository here however since you remember all of the methods in itunes repository i are asynchronous methods we will also have to turn all the metals in this controller into asynchronous methods that way we can have the asynchronous benefits all the way from the controller all the way to the to the repository and to mongodb so to do that i'm going to turn let's start with get the get all so we're going to turn this into async task of innovable of identito and we're going to append the async suffix to this method let's import a missing treating tasks and now to return the items well this is what we can do items is going to be weight item repository get all async okay and then from that we're going to project these items into these item entities into dtos before we can do that we have to put this into a parenthesis and then we can say okay so from that let's do select and each of the item entities is going to be turned into a dto via our new astitu extension method that's there you can see how it how easy it makes it this extension method to turn an existing entity into a dto and then we just return those items okay so let's go to the next method so this is get by id so once again we will turn it into async task of action result of it and dto get item get by id async and then to get the item what we're going to do now is just wait i can repository get async and we provide the id and at the end of this method we can just return that item entity we have to say as dto so that turns the entity as into a dto let's now go for the post method let's scroll down a little bit so once again this has to be an async task of action result of identity and it's going to be post async task instead of doing this we're going to uh create an item entity in this case out of the properties of create identity so we're going to say bar item equals new item and we're going to start giving it the the properties values so create individual name description description and create a date uh here's where we're going to give the current date as the creation date of this of this item also remember this is not identity or this is just item okay i may need a name space here yeah empty disney space now we can go ahead and actually create the item via our items repository that create async methods and then we pass the item and finally we have to rename this method from get the id to the new name which is get via the async the one that we just renamed because that's where the created action should point to let's now go ahead and implement our boot method scroll down so once again we turn this into public async task of i action result put async and once again we have to do things a little bit different now so i'm going to actually remove this this whole block here and first thing we're going to do is find the item now in the via the repository so it's going to be existing item we're going to see it's going to be await item repository that gate async notice also how easy it is to actually interface with mongodb via our item repository without having to write the same piece of code once and again right at the filters and all that so we just got the item just like that and then yeah if you if we cannot find the item in the database in which case it will return no we want to keep returning not found just like before and here once we find the item we will have to just update these properties based on update item dto so that's going to be existing item that name equals update identity of that name existing item the description date identity of that description and existing item that price of the identity of that price and with that we can go ahead and say await item repository update async with the existing item and finally let's go ahead and update our delete method so we're going to say again async task i can result delete async and we're going to do a similar logic to find the item as we just did with update so i may just copy this piece here okay i'm actually going to remove all this paste that okay i'm going to say so yeah so var item is dedicated async if the item is no we'll say not found and otherwise we can go ahead and say weight item repository dot remove async with item that id and then one last thing that we may want to tackle here since we are making these changes is to actually um fix an issue a kind of a breaking change that happened in asp.net core 3 where if you try to do let me go back to post if you have to do a post and do create an action into a method that ends with async with an async suffix uh that's actually not going to work because at runtime uh sp netcore is going to remove the async suffix from the method and that will make it so that created action will not be able to redirect to the right place or to prevent to produce the heaters that it needs to produce and so there's an easy fix for that so let's actually make that fix right away so i'm going to back going to go back to explorer going to open startup and let's locate the section where we do add controllers in configure services inad controllers we're just going to add a little option here so it's going to say options and then we open and close braces and we're going to say options that suppress async suffix in action names is going to be false and with that at runtime uh asp.net core is not going to remove the async suffix from any any four metres and that will make possessing work just fine so a rest api is ready to use our new repository to store and query the items in the mongodb database however we still don't have an aqua mongodb database or even a mongodb server but that's a problem that we can easily solve via docker in the next lesson we will learn about docker and how we can use it to run the infrastructure components needed by our microservices in this lesson we'll learn about docker and how it can be used to run infrastructure components needed by your microservices so what is docker docker is a platform that provides the ability to package and run an application in a loosely isolated environment called a container here's how it works we start with our catalog service which as we know needs a database to store and query for items the piece of software that knows how to stand up and operate this database in our case is mongodb the mongodb server along with all the software prerequisites has already been packaged in what we call a docker image and this image is publicly available in a place called docker hub we want to download and run this image in our box and to do that we use the docker engine which is one of the pieces that you installed at the start of this model all docker images are guaranteed to run anywhere the docker engine is available to pull and run this image we will use the docker run instruction in our box once the image is run or executed it becomes what is known as a docker container a mongodb container in this case this is a fully working mongodb server ready to respond to the requests of our catalog microservice the catalog service will create a database via the mongodb container and will start interacting with it via the mongodb driver4.net notice that even when this container manages the catalog database the database itself does not live inside the container but outside of it to ensure that it is not deleted once the container is destroyed let's try it out to start using docker in my box i'll start by opening a terminal so i'll press ctrl j and then i'll also close our navigation pane just so we have a bit more space and the first thing that i'll do is i'll just type docker run to run a container and then i'll specify the demodifier so that we don't keep being attached to the docker process all the time and then i'll do rm so this we'll use so that whenever we stop running the container it gets automatically deleted so that we don't keep hanging it around in the box next i'll specify a name which is going to be just so you can put any name here but the idea is that uh you don't lose track of this a docker container because otherwise you get a random name and it's a bit hard to identify next we have to specify a port so we have to specify which is the port that we're going to be using to talk to mongodb the among the v server so we'll specify p 27 0 17 map to 27 0 17. so this means that in order for us to reach the mongodb container we can use port 27017 is the external port and then uh in order to to to get that mapped into the internal mongodb server we have to map into 27017 also so this port is the default port that mongodb uses internally and this just means that from the outside we open kind of a window uh in order to talk to the container via 27017 and then that can be mapped into the internal port where mongodb is already listening you could be using any port in the left side as really up to you we're just choosing a default map in there then we'll specify a volume the volume we're going to be using so that we specify how we are going to store the database files that mongodb is going to be using so we're going to say mongodb data colon slash data slash db so this section on the right side of the column slash it is tv is a default location where mongodb stores the database files so this mapping means that any time that the mongodb server tries to store files inside the container under slash data tv those files are actually not going to be written inside the container but outside of the container into this location called mongodb data which is part of our local localhost machine so it's outside of the container so this is the way that we can prevent those database files from being deleted anytime the docker container gets also deleted and finally we'll specify the name of the docker image that we want to run in this case is now i'll hit enter i'll perhaps expand this a little bit more so at this time uh docker is pulling the all the layers of of the mongodb docker image into my box okay so layer by layer it gets unloaded uh just the first time uh and this this may take a while but the second time that you do this and any subsequent time this is going to be much faster because the image is already there so if i did if i did that again it will run instantly then we can confirm that the docker image is actually executing by just running docker ps as you can see the docker image is up and running it's been running for 14 seconds right now okay so now we can try running our res api against this soccer container and see how that goes so i'll hit a five here and i'll go to our swagger page so the first thing that we can try just to verify that there's nothing here because it's a brand new database is our get all items um operation so i'll try it out i'll hit execute and as you can see there's nothing in there the databases is all empty so let's next let's try creating something so i'll go to our post operation try it out and let's let's try to create something here so we will go back to our back to our potion sample so i'll just name this potion and this is going to restore a small amount of hp and the price is going to be five and with that i'll hit execute and as you can see the item has been created we got a 201 response code create that action here's a response body and we also got the location here to find our item so in fact we can copy the this id of this item and we should be able to use our get by id operation to find it so i'll collapse this i'll expand get items by id i'll try it out paste the item here execute and certainly we can find the item so the item has been stored into the database but now if you wanted to know how this item has been stored into the mongodb database there's an easy way to figure that out so i'll go back to visual studio code and then i'll just stop and close this and what you can do is use a mongodb extension for visual studio code so to install that just go to the extensions hub on the left side look for mongodb and should be the first hit on the left side so i click on that i'll click on install and now there's a new icon showing up on the left side for mongodb which i'll click now and then i it should connect straightforwardly into the mobile dvd database just by expanding this node for localhost 27017 since it's the default port it just connected so i'll expand this and as you can see there's a catalog database available right there so it has been created if i expand that there is an items collection available this is the one that we will be storing our items and then i'll expand that further and as you can see there is one document already created into the catal database if we expand that we can see that there's an item in there however if we try clicking clicking on it let's click on it but you can see you can see most of the members of the created item but some of them are not easy to recognize like for instance the id is not the gui that we were expecting and the created date is a bit hard to read the other elements are there so potion description and price so how can we get a better a more friendly uh the more friendly representation of these items like id and created date so ideally we want to see something more easily recognizable so there's actually an easy way to to fix this let's go back to our explorer and let's go to our startup class okay once again i'll collapse this so to fix the json representation of our items we just need to register a couple of mongodb serializers we can do this in the configured services method of the startup class we will talk more about the role of startup in acefinite core apps in next lesson but for now let's just think of your services as the place where we register services that can be used across entire application so let's scroll down a little bit here we are in configure services and what i'm going to do is just expand this a bit and i'm going to add visual serializer and for this i may need to import namespace mongodb that based on that serialization that register serializer and here we're going to provide the serializer we want to use in this case it's going to be new good serializer and then i'll import mongodb bsun serialization serializers and then it's going to be and type and then import one more namespace that string okay so that means that anytime we store any document into mongodb with a good type it will be stored actually as a string as opposed to the representation that we're looking at a moment ago and we're going to do pretty much the same thing for our the datetime offset so in this case we're going to say so instead of quick serializer we'll use date time offset serializer and then this line now says that anytime we store any document with a datetime offset a property it should be stored that probably should be stored as a string so save that and that should be enough to fix our representation of the items in there however uh to to not mix things what i'll do now is i'll actually delete our existing database so that we can recreate it with the proper esterization type so i'll close this here and i'll go back to our mongodb extension and i'll right click in the catalog database i'll say drop database i'll type the name enter and if we refresh this there should be no database available anymore okay so with that let's hit f5 once again okay back in soccer ui let's see if we still have the post available here yes we have so i'll just refresh the page and i'll go back to post and once again we should have no items so actually i'll go to get all items try it out execute so there's no items because a new database has just been created because we deleted the previous one so back into post i'll try it out and i'll paste the what we typed a moment ago so it's a potion price five restore small amount of hp and i'll hit execute and once again the item has been created with this id and this time we'll go back to visual studio code and let's see how that got stored so i'll refresh this right click refresh expand catalog items documents and as you can see the id it already looks like a good and if i click on it and i'll close this a bit now we have a much friendly representation of the item the id is a proper good and the created date is a daytime offset that we can actually understand so that's the effect of using these serializers in there so let's continue using our res api let's make sure all the operations are working properly so as we saw we just created this item and if we use get items by id we should be able to find it so let's confirm that paste it there execute so yeah indeed we were able to find the item now let's try an update on an item so to do that let's use the put api so i'll click and expand this i'll say try it out let's grab the actually the id of that item once again so it's over here here's the id so i'll paste it here so we're going to update that potion and then for the for the elements of this of this potion let's copy also a few of the existing elements so i'll copy this from our gave id route into here actually inside there i'll remove this extra comma and so the only thing we're going to define here is just the price of the potion so instead of being five i'll say it's going to be price seven and i'll hit execute i've got a 204 so no content successful no content so this means that the item has been updated and to confirm that let's go back again into our get by id route let's execute again and as you can see the price has been updated so output route is working just fine and for the final exercise let's try to delete this potion right so i'll go ahead and copy again the id of the position and let's collapse this and that and let's go to the delete route try it out paste here hit execute 204 no content and it is a success so the item should no longer be there so i'll try to actually get this item by id once again let's see what happens i suspect it's 404 it can't find the item and in fact if we go to get all items there's nothing there so the item was deleted okay so at this point we have a fully working res api with all the basic cloud operations that's working against a mongodb database but we still need to polish a little bit the code base that we have so far so in the next lesson we will learn about the dependence injection technique and the net configuration system in this lesson we will learn about the dependency injection technique and the net configuration system what is defense injection to understand what dependence injection is we can start by thinking about a class that uses some other class for instance our items controller uses the item's repository when you have this relationship where one class uses another class we say that this second class is a dependency of the first class now if instead of constructing the item's repository object directly as we are doing so far we receive an instance of items repository in the items controller constructor then we are injecting item repository into itunes controller this is what we call dependency injection but also notice that the constructor is not exactly receiving an instance of item repository but instead it receives an interface called items repository this relates to what we call the dependency inversion principle the defensive version principle states that code should depend on abstractions as opposed to concrete implementations let's bring again our class and one of its dependencies dependency a currently the class depends directly on dependency a however we can change this so that the class instead depends on an abstraction which in the case of c sharp is an interface and then we can have the dependency depend on or implement the interface why would we do this well by doing this our class implementation is decoupled from the dependence implementation in such a way that if we ever decide to switch to a different or updated dependency our class does not need to change at all the only thing that the dependencies need to do is to implement the interface that our class depends on so by having our code depend on instructions we are decoupling implementation from each other and this also makes our code cleaner easier to modify and easier to reuse now that our code is decoupled from these dependencies we have a new problem how and who is going to construct the dependencies imagine once again that we have our class which depends on an interface implemented by dependency a since our class cannot construct the dependency directly because it only knows about the interface a third actor comes into play which is called the service container which in asp.net core is known as iservice provider loading application startup which typically happens in serap.cs in asp.net core apps we would register our dependencies with the service container and this one in turn builds a map of all the register dependencies then eventually when our class needs to get constructed the service container first finds constructs the dependency or reuses it if it already has been constructed and then injects it into our class as it creates our class instance this is very powerful because you could even have dependencies that depend on other dependencies but as long as they all have been registered with the service container they will all be resolved properly whenever any class needs them during the application life cycle let's also talk about configuration at this point our service is able to talk to our mongodb database via the host and port information that have been hard-coded in our service implementation however this is not ideal since eventually the mongodb docker container will live outside of our local box where localhost will likely not make sense and port 2717 is not guaranteed to be available luckily afia net core supports a few configuration sources that are able to store and provide such configuration details to our service when needed one of the most popular sources especially for local development is the app settings.json file where we can store all sorts of computational information that we expect could change across environments like the database host and port and the good thing is that just like this one there are several other sources like command line arguments environment variables local secrets and even the cloud all these configuration sources are automatically read for us and loaded into the configuration system during host startup which is configured in the program cs file in asp.net core applications and from there we can get access to them typically in our startup.cs file let's now update our catalog service to take advantage of both the penis injection and the acl net core configuration system in order to start using dependence injection in our microservice we will need to start using interfaces as opposed to concrete types when constructing dependencies let's start by updating item repository so that it implements an interface that we can use in ads controller so let's go to our repositories directory items repository and then we want to do is to extract the interface that represents items repository and we can do that by clicking on item repository and as you can see there's this yellow light bulb over here you can click on that one and then you can click on extract interface by doing that as you can see the full skeleton of the interface has been extracted out of the item repository class and item repository is now implementing items repository our new interface we also want to have the interface living in its own file just to follow some good code organization across our microservice what i'll do is i'll click on i items repository i'll click on the light bulb and then i'll click on move type to itemsrepository.cs now i add the repository leaves in its own file over here on the left side i add repository in the same repositories directory and so with that done we are able to start doing dependency injection of item repository into the access controller so i'll open the controllers directory i'll go to items controller i'll scroll up all the way to the start of the class and i'll start by updating our items repository definition here so that we actually use i item repository as opposed to item repository and i will not create an instance right there it is time to introduce a constructor for this controller so i will do public items controller and here we are going to inject the item repository dependency so i items repository item repository and here we'll just do this that oh sorry this that item depository equals item repository so just by doing that uh at the repository has been injected into ideas controller now the same way that we are doing this we also want to use dependency injection in items repository itself so let's go back to that file because we don't want to be constructing the mongol client like we're doing it here we want to just receive an instance of our of our mongol database or imongo database directly as appendix injection so what i'll do is i'll just declare in itunes repository and imongo database object and we'll say database and with that we'll get rid of these two lines so now eisenhower repository is ready to receive an instance of database via defense injection however now that we have removed those lines we need a way to actually construct this database object and configure it so let's go into the configuration part of this now to configure the the host and the port that our service needs to connect to what we can do is to declare these settings in our app settings.json file so let's go to app settings.json and here's the ideal place for you to declare these kind of configurations that could change with different environments so what i'll do is i'll open up another section here let's call it mongodb settings so we'll open up a section i'll put a comma also here and then the first setting is going to be the host which in our case is we're running against a a server in our local machine it's going to be just localhost and the port is going to be 27 0 17. the default port and the one that we've been using in our docker container we are also going to add another settings section to define our service name this service name is going to be used across a few places in our microservice so let's declare that just on top of mongodb settings we will name it this section is going to be service settings service settings and we'll just declare one property here which is going to be service name which in our case since this is a catalog service we will just put the value of catalog okay so now we have a setting for the service name and for the mongodb host and port now the thing is how do we consume these settings in our codebase so there's a couple of ways to do that but i think the most straightforward way is to define a class that represents each of these two settings so that then our codebase can start using them right away so to do that what i'm going to do is just right click on play that catalog service or create a new folder that we're going to naming settings and in this folder i'll declare classes for both service settings and mongodb settings let's start with mongodb settings actually and i'm actually going to copy the name of the settings so to make sure that the class that we create here matches exactly the name of mongodb settings in there so i right click new file mongodb settings dot cs basically namespace going to be play catalog service settings and let's declare our class mongodb settings and just as we just did it should have properties for host and port so let's declare drop string host and prop string for tactile this should be an integer so prop import and then since we are not planning to change these settings after the the microservice loads we will switch from this this setter from set to init so that will prevent any anybody on any piece of the code to modify the values after they have been initialized next we're going to also declare another property kind of a calculated property that's going to define the connection string to mongodb so we're going to declare public string connection string and we'll do a little bit of string interpolation here where we're going to declare mongodb and that's going to have the host import so the host comes from our host property and the port comes from our port property okay so this is what we call an expression body definition so it's a property defined directly by the value on the right side right so we have a connection string there the next thing we need to do is define a type class for service settings so i'll copy the the name of service settings here and then again alright click settings new file service settings dot cs let's declare again namespace catalog service settings public class service settings and the only property that we have for this one is the service name so prop string service name and again this will be in it now that we have all this defined it's time to start constructing all these services registering i'm constructing and registering and registering and constructing all these uh services that we'll be using for depends injection and also taking advantage of configuration so to do that we'll go to the startup.cs file and i'm going to collapse this to get a bit more space so we can see and the first thing that i'll do is i'll go to the top of the startup class and i'll define a variable a local class level variable for our service settings just because we'll we will be using it in a few places across classes subsequent lessons so private serv service settings service settings and i'll have to do control dot to import play catalog service settings all right and then just before adding controllers i'm going to open a section here where first we're going to retrieve the value of those service settings so we're going to do is service settings equals and here's where we access the net configuration system where we'll be at the configuration property that we have available right here at the top configuration so we're going to say okay so configuration we're going to get section so we want to get the section that has the name of our service settings class so this is what we wanted to make sure that the class is named exactly as the name of the configuration and what we have got in that we're going to turn it into the actual type so we're going to say that get service settings there so with that we are digitalizing the value of several settings that has already been loaded into the temp configuration system into this service settings variable here the next thing we're going to do is to construct our mongodb client to do that we're going to be using our services collection so we will do services which we receive in the um as a parameter to configure services we're going to say at singleton uh add singleton allows us to register a type or an object and make sure it makes sure that there will be only one instance of this object across the entire microservice in this case so any class that needs it will get this one instance so it so they can use it so here we're going to receive the service provider okay so now we'll open an expression here and i'll close it this with that and just like we did with service settings we're going to now define or retrieve our mongodb settings so i'm actually going to copy this section here and we're going to say this is going to be mongodb settings okay so is configuration get section name of mongodb settings and then we will again convert it into the actual mongodb settings type now that we have the settings we are able to construct the client which like i said before is the the class we need to use to actually connect to mongodb so we will say client is a new client and i'll import mongodb driver here and here what we want to pass is the connection string so to pass the connection stream we will do mongodb settings dot connection string and finally now that we have the bongo client we can get the instance of the database object that we care about so we will do return client get database and then what's the name of our database well the name of our database is going to be the one that we defined for the service name service name is catalog our database will be just catalog so service settings that service name and that's it so with this uh with this section we have defined a singleton object that represents a an imongo database that's going to be injected as remember into um items repository over here is going to be landing over here i'm on the database so here's where we're constructing and registering it with the service container and then one more thing that we need here is to uh also in register the items repository dependency so we're going to be doing services that add singleton and then we will use our new i items items repository interface and then i'll import the play catalog service repositories namespace and then the concrete type is going to be items repository all right so this is this registration is a bit different than the previous one because the previous one in the prison we're cons explicitly constructing our mongol client and the mongol database before registering it with the service container well in this case we're just declaring which is the type that we want to register and which interface implements and the exponential runtime will take care of constructed that instance whenever it is needed so we should be ready to try this out but what i'll do is i'll place a few break points so we can see how things start lighting up as they do so i'll put a free break point so i'll put one over here then i'll go to item repository and i'll put one in the constructor over here and i'll also go to our items controller and i'll put another breakpoint here and now i'll hit f5 okay so we can go to our soccer ui page i'll go slash swagger and of course we don't have anything in our database right now but regardless our servers will need to construct all these dependencies to be able to figure out that this is actually no items right now so i'll open up our get all items operation i'll click on try it out and then i'll click on execute now back in vs code and now collapses a bit we are now in our startup file and notice that we right away we are entering into the add singleton section here this is because uh so there is one or more services that need this imongodb objects so if we inspect the value of mongodb settings we can see that we already have defined the host port and the calculated connection string is right there and that's what we are using to fit into the client connection string we should also have a value for service name here from service settings has been read from configuration and it's been used to get the database form that we're going to be using this database is being will be constructed the first time and the next time it will be just reduced so i'll hit continue here and now we are into items repository which now is able to receive retrieve that instance of the imongo database object that has been constructed and it's been injected here and it is via that one that is going to be able to retrieve the items collection that's going to be used across the is repository then i'll click continue and now we are in the itus controller which is not able to now able to retrieve to receive that injected as a repository that is going to also be been used be used for all the operations i click continue and we're back into play catalog service the socket ui which of course it says there's no items right now but we know we can easily go ahead and start creating items updating items and all these things with the swagger ui but yeah so depends injection is configured and the configuration system is enabled too so we have reached the end of this model with a fully working decoupled and configurable microservice that is able to store and guided for your catalog items in a mongodb database in the next module we will introduce our second microservice and we'll be learning about the multiple challenges of having microservices talk to each other this module is an intermediate step to get ready to build our future microservices we will learn about a few new tools that will help you as you start working with more microservices and we will build a useful library that we will use in future models here's what you will achieve after finishing this model you will learn how to use postman as an alternative to swagger ui to interact with your microservices you will generalize the items repository so that it can be used with any future entity you will create a nuget package where you will place all common classes that you would like to reuse in future microservices and finally you will use docker compose to simplify how to run mongodb and the multiple infrastructure services to be used in future models let's get started in this lesson we will learn about postman which is a popular api client that we will be using starting with this model postman will allow us to interact with our microservices res apis without having to open a browser to navigate to the swagger ui page of each of the services in addition it will offer us a few additional capabilities that will prove useful across this course the only additional tool required starting with this model is the postman client which you can get at this location let's get started let's go ahead and install postman i'll go to the postman download page at postman.com downloads and here i'll just scroll down a little bit i'll click on download the app i'll pick my parent system and that will start download in the same way depending on your operating system you can choose the mac os or linux version this should take just a few seconds okay so it's downloaded i'll click on the installer and yeah the way that installer worked for pulseman is that it will just pop up this screen here so it's already installing the application uh it will take a few seconds and then the our the postman ui will just pop up in your screen and here it is and so at this point you have the option to create an account with most men if you want to keep track of your collection settings and a bunch of things that you may be interested in but in our case we really don't care about that at this point so i'll just click that link at the bottom side here skip signing in and take me straight to the app so i'll just click on that and then we are in the postman uh user interface the first thing that i'll do here just because i don't like this theme at all so i'll just go to settings over here settings teams and then i'll switch to the dark emote setting okay so now that we have postman available let's go back to our catalog service and this code and let's start waiting for its several apis so let's minimize this i'll close this browser and yeah here we are in the catalog service and then yeah i'll just do f5 all right so as usual the browser opens but this time we are not going to be using the browser we are going to go straight into postman over here and here uh what you can do to start creating your rest api is uh if you have the launchpad open like me you can click on create a request over here or if you don't have it open you can click on this plus button to open a brand new tab in this tab what you want to do the first thing you want to do is figure out which is the verb that you're going to use for your res api if you click on this drop-down you're going to find a bunch of http verbs for the different operations so let's say that we want to start by doing a get uh so click on get and so that we want to get the list of items in our catalog api uh so then you want to type here the url of the address api and if you don't remember the the host where you're running your web server you can easily find that out by going back to visual studio code and here you can find that that url either right here in the debug log where it says now listening on is right here or you can also find it if i scroll down this a bit and then you open properties launch settings.json is right here close to the bottom where it says application url is over here so https localhost 5001. so i'm going to copy that and back into postman and so i'm going to paste that over here and then what you want to do is add the route for our controller so once again backing visual studio code if you open controllers iris controller you're going to find a route right here so router is items to copy that back into postman and i'll say slash items and with that you can just hit send and that's going to query the rest api now if you get an error like the one that i'm getting down here which says ssl error unable to verify the first certificate this is actually expected is a default verification for the certificate of your web server since we are using a self-signed certificate that comes bundled with asp.net core that's not really a friendly certificate for postman but it is okay to get past that verification because it's just a local web server for development purposes so what i'll do is i'll just click on disable ssl verification and that's going to go ahead and i'll just close this and that goes ahead and queries the rest api without issues of course we don't have any items available in the database right now so that's why we see an empty array over here but we can actually try out to create a brand new item and to do that what i'll do is i'll click on the plus icon over here which opens a new tab and i'll switch from get into post and once again i'll paste our our entire route here so i'll copy from get i'll paste it here in post and then we want to do is go to the body section over here and we want to choose raw and at the end of this section i'll pick json so i'll open up this and here we go where we can define the body that we want to send to this post request so i'll open up a section uh as a json section here and i'll start typing the elements for creating a in this case uh an item so if you remember the the elements are a name so we need a name and let's say we go back to our portion example so i'll just say potion then we need a description a description is going to be restores a small amount of hp and finally we'll set up a price which is going to be let's say five okay so with that done i'll do this i'll go ahead and hit send and as you can see the item has been created okay we have an id and we if we wanted to we can now go back to the get tab here and we can query for items once again so i'll click on send and now we can get items so just like this you can keep going on and using the rest of our rest api operations by opening new tabs and opening and using the different verbs over here however each of these times you'll have to remember what to put exactly on the on both on the url and in the case of pause for instance uh the body and the elements that you want to use uh for the uh for the for the payload to send in that body right uh so what if you don't remember exactly what to put in all these cases so what i'd like to do is just show you another way to do this to simplify a little bit this this oral process so what i'll do is i'll just right click here and i'll close close all tabs so actually i'll say cancel let me close this down save close that so one thing that you can do if we go back into our browser over here is we can go ahead and find the open api specification for our api so if i go to slash swagger hit enter we're back into our soccer ui page but this time we're not going to use any of these methods we're going to do is click on this if you can see this swagger.json link over here i'll click on it and this opens the open api specification so this describes the entire res api in a standard way so what i'll do is i'll copy this entire url and then i'll go back to postman and i'll go into the import button over here i'll click the link section and then i'll paste that url over here click continue and finally i'll just say import and now if we go into the collection section over here you're going to see that now we have a a description of our play catalog service listed here with all the requests so if i open this and there's the items the items route and if you open that you can see that we have routes a forget and for post and also if we want to go by id we can go ahead and get an item by id we can do the put which requires an id and we can do also the delete so this time if you want invited to get a ghetto items what i can do is just click on get items and then that's going to open a a tab with an already filled in verb and url to go ahead and request the items however you're going to notice one new thing here which is the base url so the visual represents uh really the root of your or where you're hosting your res api at this point so this is the localhost 5001 section so postman just doesn't know that information just yet it just knows about the routes and the payloads so to fill in this this variable here base url what you can do is go to back to play catalog service over here click on these three dots click on edit and then you go to the variable section here and then you want to put a value for for current value so what i'll do is i'll just put https localhost 5001 okay i'll also put that in initial value this is what's somebody else that wanted to reuse your postman collection it would have as an initial value if they wanted to so i'll just keep the same value for both of them so then i'll just hit update and now if we hov a hover over base url you can see that now we have the result value being pop-up there uh for our res api so now i can go ahead and hit send and once again i get my items but more interestingly if i wanted to do a post this time i can click on post and then again the the url the birth is filled the url is right there and the body is already pre-populated with all the elements required for this api let's actually try to do a put so i'll go ahead now into put and again the url is pre-filled in there we want to do is to in this case first we need the id of the item which we can get from the get items tab here so i'll just copy that id back to put and i can put the id right there and then in terms of the of the body i can go to the body section and like i said it is pre-filled so i just have to put the elements for this body so i'll actually just copy those elements from here okay and now do a proper indentation and so here's where we can go ahead and update something about this potion so i'll just update the price again so i'll say seven and then we're going to click on send and we got a response uh 204 no content meaning that it succeeded and so now we can actually try let me copy the id of this item we can try our get buy id api and then again the url is pre-filled i'll just paste the id over here i'll hit send and there it is we got a our potion so as you can see it is pretty handy to just import the open specification of an api specification into postman and be able to be able to quickly very quickly start working with your rest api imposement now a few other things that are available in postman as opposed to our previous swagger ui page is things like for instance of course we have the the concept of these collections which in fact you can actually export if you wanted to and share this with somebody else in your team or some of your teammates you can easily export this collection and you will do that by clicking these three dots and you can click on export and there's going to be a few options for you to export this for somebody else then also we you have a this this tab over here that says history this will show the history of all the previous implications of your res api so if you wanted to go back to something that you did in the past with the specific payload that you did and url uh you can do that so this is going to keep a long list of all the the queries that you've made to your api across your different sessions there's also this concept of environments over here which you can use to define the different environments where you want to invoke your request api so if eventually you're not just running in your localhost machine but perhaps you have deployed this to some a cloud environment you can define variables over there so that you don't have so that for instance device url automatically changes as you change the environment that you're specifying over here that way you don't have to keep opening more and more tabs for the different environments there's also the ability to specify authorization options over here for the different authorization types uh so that you can for instance generate a generate and use uh authorization tokens to call your res api if your recipi is enabled for that that's actually something that we'll look at in a future a model okay so now that we have done that uh one more thing that we want to do is to since we are not going to be using post one we don't really want to be opening browsers all the time so how can we prevent the browser from uh keep opening every single time so let me just go back to the browser and i'll just click close this and then i'll go back to visual studio code and let's stop and close this and what you can do is to go back to we go to explorer and we're going to go to that vs code launch.json and you want to look for this section that says server ready action so this section here is the one that visual studio code uses to define if they wanted to open a browser after something happens with the web server in this case it's just looking for the message that says now listening on so when it finds that it knows that it needs to open the browser so in our case we don't want to open browsers anymore we'll find with postman so we're just going to remove this section delete and now if i do f5 okay no browser is going to open we just stay here uh but as as always you can just go to postman and start creating the api like we already did okay so that's it for this lesson and in the next lesson we will start extracting a few of the classes that we are using in catalog microservice into some shared components that we can use in our future microservices in this lesson we will learn about the need to reuse common code across microservices and how the nuget package manager can be used to package and share code across services in a straightforward way one of the things that you will likely realize as you start building more than one microservice is how much code starts getting repeated between each service implementation for instance our catalog microservice currently has a repository implementation for querying and storing data in its mongodb database it also has a couple of settings classes to more easily use the different service configurations that are stored in our app settings.json file eventually we will also add classes to interact with our service broker code to add instrumentation to the services and likely some more code that is not directly related to the purpose of the microservice the problem with this is that as soon as we bring in our second microservice the inventory service we would likely need to copy to it that same code with very little modifications this is time consuming and goes against the don't repeat yourself principle which states that every piece of knowledge must have a single unambiguous authoritative representation within a system which in our case means that our common code should live and be maintained in a single place therefore we could be tempted to keep our common code in one of our microservices and have all the other services simply reference that project to get access to the common code however this is not a good idea because microservices should be independent of each other to ensure each of them can evolve quickly and have no ties to the internal implementation of others we can solve this problem by introducing a new library project that we will call the common library and then we can extract all the common code into it the common library becomes the single place where we have all the code that is not specific to any microservice and therefore is the single place where we will perform any updates to it when needed but then how can we make the code in this new common library available to our microservices we could have our microservices add a direct reference to the library project file but that's not a good idea because as new members join our team each of them might want to work on one microservice or the other or even in the common library and therefore they will only graph the code base for the project they are interested in but not the code basis of all projects all the time plus eventually each microservice and the common library should get their own independent source control repository where they can be tracked and built independently so if the microservice projects can access the common project directly what can they do here is where we can use nougat which is the package manager for dotnet with nuget we can execute a simple command like dotnetpak to bundle all the output files from the common project into a nougat package another package is nothing more than a zip file with a new pkg extension that contains all the files that are to be shared with other projects now each of our microservices can reference the nougat package to get access to everything that the common library has to offer and the good thing is that microservice projects don't need to know where these nuget packages are hosted we will initially place the package in our local machine but eventually you will likely want to host them in a cloud-based location either accessible just by your team or by anybody on the web the important thing is that regardless of the location you won't have to change how the microservices access the common code with our new common noked package our common code is now maintained in a single place and the time to build new microservices is significantly reduced in the next lesson we will extract our current common code into a new common library and we will produce our first nuget package that the catalog microservice and every filter service will be able to reference to get quick access to the common code if we take a look at our item repository class over at repositories items repository we will notice that there's a lot of code here that we will need to reuse in future microservices and the same goes for our settings classes over in the settings directory mongodb settings service settings we can certainly reuse these in future microservices but before we can move anything to a new shared library we will need to do some good refactoring to keep the generic pieces separated from what's really needed in the catalog microservice so let's start by looking at our items repository and if we take a closer look at what's going on here there's one piece that's really repeated a lot across this class and that is the use of the item entity the item entity is being used uh in several cases like for instance in ghetto lacing is being used to return the items that are going to be queried and we are also filtering by the id of this item in both in engage async method and also in the update async method will filtering by id and also in the remove async method so we need to find a way to generalize the use of this entity so that it can be used in like i said in a more general way in this repository so let's actually go to the item entity so right click go to definition but what we're going to do here is to actually extract an interface out of this item class uh to nail down narrow down the pieces that we really need to generalize about the item so we're going to do is just click on the light bulb and say extract interface and now we have the item interface here that our item class is implementing however we don't want to call this interface i item we actually want to call it i int and this ai entity is what our item class is going to implement but also we don't want to have all these properties in the interface but only daily having the id will be good enough to be used in the repository class we're going to implement now we also want to move this interface into a different file so i'm going to click on the light bulb and i'm going to move the type to indit.cs okay so now we have a i the item entity that implements i entity that is in the i entity.cs file over here now what we're going to do is to before going back to the item repository let's go to the items repository class and see how we can generalize this so to start with we don't want this class to be about just items anymore but about a generic type and the way that we can do this is to by renaming this interface into uh instead of iot depository is going to be i repository and it is going to be off a generic type that we're going to use name t where t represents the actual entity that's going to be used in a specific microservice so this t will add a constraint here where t is has to be and i entity the interface that we just defined so whatever we use for t it has to be a class that implements the identity interface so now that we have that generalization we can say that all of our methods actually use this this t type so for instance instead of having item here we're going to name it as t and the same the same way we're going to do for the item that's going to return in general lacing the item does return in get async and also the item the entity that's received in updated sync okay so with that there's no longer a mention of the item type anywhere in this interface so with that done we can now go back to our items repository and also generalize it to represent a more generic repository so instead of being an items repository this is now going to be a repository that is going to be off some type so again we're going to use a type t to represent the actual entity that's going to be managed by this repository and also our repository class now needs to implement the i repository of the interface again where t is an i entity okay so let's also rename the constructor to be repository and let's start changing this so that it actually to start removing everything related to item from this class so one of the things that we have to get rid of is this constant that is the collection name items uh since this is not going to be just about items anymore let's remove it and what i'm going to do is just copy collection name just the name of the var for the constant and remove it and now we are going to receive that collection name as a parameter in the constructor so we're going to receive string collection name so that's a collection name that's going to be used when we try to retrieve a collection from mongodb from here on okay and so now we need to start moving forward and start analyzing things so let me just get a copy of t and so anywhere where we find item we want to replace it with t so this is a db collection of t filter builder of t builders of t dot filter and we get a collection of a t a i t entity when we do get a lacing we have to do t again and again when we do the filtering so get is of t d over here it's all generic also create async should be t update async should be also t filter definition of t and notice that since our actual since our interface has the id property it doesn't really care that it doesn't know what's a real item as long as that the real entity sorry as long as that entity implements a identity it is able we know that there's going to be an id property a quick id property that we can filter by and finally let's change our remove async to also deal with just with t all right so just to confirm let's make sure we don't have item anywhere in this file anymore yep there's no more item here so let's also rename the file by the way so this should be mango repository and this other file here should be a repository and with that done it is time to start fixing all the references to our repositories so let's start by going to our controllers class items controller and let's fix things right so this is no longer an iates repository it's just and i repository of type item and that is what we are going to be receiving in the itunes controller in the constructor here okay next thing that we need to do is to fix the way that we are registering the repository in startup so let's open up startup and let's see how we are registering the repository over here so this is what we're doing today at singleton i attend repository item repository so we will switch to a more a more concrete way of defining this singleton because now we need to specify a parameter as an input to the repository so remember in manga repository now we are receiving a collection name so we cannot just just expect to all parameters to be injected automatically by the service container for us so we need to be more explicit so let's update the repository registration to start with we are no longer using the item repository interface we are using a repository of type item and let's see if we're missing something so let's add the service entities namespace so it's another repository of item we will notice is define an actual class as a second parameter here and then we have to specify this service provider service provider just like we did in the other at singleton call let's open braces here and now before we can create the instance of the mango repository first we need an instance of the imongo database because remember we actually registered an imongo database in the previous singleton call so how can we get an instance of such a registered service so that's where you can use the get service method of the service provider so just like this so bar database equals service provider that get service i database okay so anytime that you need to get an instance of a service already registered in the service container like we did with imongo database uh you just you just need to call get service on service provider and this will work as long as that service has been registered before the call that you're going to make here and then having that imogo database instance we can now return our new repository of type item and then we need to provide two parameters first one the database the one that we just got and then the collection name that so far is being just items okay so that should do it let's make sure everything is building successfully so i'll do ctrl shift b and indeed everything is building just fine so at this point we have generalized our repository class so that it can be used with any type of entity however it feels like we're writing too much code on startup to register the mongodb related classes because look at this we have to do register serializers we have to do the singleton registration for the client for the database and then the other singleton for the repository so in the next lesson we will introduce a couple of hand extension methods that will simplify things quite a bit for this and for future microservices so let's take a quick look at everything that we have to do in order to use our mango repository so far so here i am in a startup class and the first thing that we have to do is register the the bson serializers in order to change the way that we store codes and date times then we have to get the mongodb settings the the movie settings section for an app settings the json in order to construct our client and then we can create our imongo database that we registered as another singleton and then finally when we have that we are able to retrieve that imongo database and then construct that repository for the items collection so let's see how can we simplify all these lines to make the life of future microservices much easier what i'm going to do is create a new extensions class inside the repositories directory so i'm just going to right click here i'm going to create extensions that's yes not to be confused with the other extensions that we have over here this is a new class let's give it a namespace like dialog service repositories so let's name this class public static class extensions and let's declare a function here so it's going to be public static i service collection because we're going to be extending a service collection here and let's name it admongo and it's going to receive we're going to extend the i service uh collection object okay so it receives a service collection and it will return a live service collection let's see if we're missing a space so let's add the defense injection space there and here let's go ahead and grab a few lines from startup so let's grab these lines over here and let's go ahead and add missing nice bases so i'll do visual serialization i'll do serialization serializers and then i'm going to device vision okay and then we will need service settings but we will not receive them here we will get them over here as bar service settings but one thing that you can notice is that we don't have an instance of configuration here just like we had in starbucks where it was uh when it was a property that we received as part of the constructor so we can do is use a service provider to explicitly request a an instance of office services has a varying register so configuration is registered already by asp.net infrastructure so we should be able to request it at this point what i'm going to do is just say bar configuration is service provider dot get service and the type of service is going to be just i configuration okay which needs the extensions configuration space so now we can flip this configuration into just configuration with with a small cap c and then we are also missing another namespace here which is the service settings namespace okay so we get the configuration we retrieve service settings mongodb settings we construct the client let's add the missing space here too and that allows us to return the imongo database finally we're going to return the services collection just to enable the fluent use of this extension method so that will register the imongo database instance and now let's add another method to register the repository itself so i'll open up another menu here let's call it public static my service collections go to return add repository it's going to be the name and then we'll specify a constraint of t for the actual entity type that's going to be used and then it's going to extend a service collection the name is going to be services and then remember we have specify a collection name in order to create a repository so let's receive collection name as a parameter we also need to specify a constraint for that for that t parameter so t the the the t type that's going to be used has to be a type that implements i entity okay so we may need another namespace let's first expand this save it let's send this to the other line and let's add the service entities namespace okay so this will be useful to register uh repository with any type of entity but that entity has to implement i in the indit interface so now what we can do is go back to startup and grab these these few lines for the i brother registration we'll copy that here and then uh to make it generic we're no longer going to be using item here but just d and then this also registers as and we no longer hardcode the collection name we're going to be using the collection name parameter and finally to keep it fluent we return services once again so with that we should be able we should be ready to start using these extension methods so let's go back to startup okay so we're going to go ahead and remove this serializer registration let's skip several settings for now in case we need it later but we definitely don't need any of this stuff so now what we can do is just say services add that registers are a client and a imog database and then since this is fluent we can say at mongol repository we specify a type in our case type is item and then we provide the name of the collection which is still items so with that done let's just make sure things are keep working properly so i'm going to hit f5 to start a web server and i'm going to go into postman and i'll do again our simple get all the items request i'll hit send and yeah it keeps working just fine but as you can see the coding startup is way way simplified in the next lesson we will see how to move all of these common classes into a new shared library that can be used by all of our microservices it's time to move the common code with refactor from catalog microservice to a new shared class library that can be used by both catalog and any future microservice so to start with i have opened a new visual studio called instance i have opened my terminal and i am in the project directory so here we're going to create a new directory let's call it play that common and i'm going to open that directory in visual studio code all right now as usual i'm going to create a new sources directory src and here's where i'm going to open a new terminal to create a class library not a web api project but just a class library as we need what we can do is use dot cli by doing dot net new glass sleep and then we will give the name of play dot command so let's just erase the files that i can see that we can see on the left and then the first thing that i'd like to do is to generate the files that visual code needs to build our project but before we can do that we have to make sure that the omnisharp server is running the omnicharge server is the the component of the c-sharp extension for visual code that takes care of a bunch of productivity improvements in visual studio code like the generation of these files so what i'll do is just to kick off the object server i'll just click on class1.cs and as you can see on the bottom here omnisar servers is starting already and with that i can now go to view command plate that then generate assets for build and debug so that will go ahead and generate our vs code folder with the dash.json file inside and now that we have it i'll click on it and i'll go to this section to make the the build action the default action uh for building our project so i'll just add our group folder just like we did with the catalog microservice i'll select build easy fall true and save okay so with that i'll go ahead and close this and i'll delete this class one file we don't need it and now it's time to add a few nougat packages that our shared libraries our shared classes are going to need so first i'm going to switch to play that common and here i'm going to start adding a bunch of packages so i'll do net add package mongodb.driver okay so that's for mongodb now we need a couple of packages for the configuration related classes so donate a package microsoft extensions configuration okay we'll do that one and configuration.binder lastly we have to add the extensions that dependency injection and nugget package which is going to be used for everything related to the service container that we're using for the penis injection in this library with that done let's go ahead and start creating a folder to bring in our files so first of all that i'm going to create a right click and play that comma new folder folder is going to be settings and here's where we're going to place the settings files that we have in catalog so i'm going to go back to catalog folder the catalog directory or here and i will open settings and i'm going to copy these two files mongodb settings settings settings copy and back in common i'm going to paste those files here and i'm going to close the terminal for now and now that we have them here let's fix the the name space so that it matches our current uh our current project so this is going to be play dot com dot settings so vote for tv settings and for service settings okay with those files done let's go back to catalog and let's bring in our i entity interface i'll copy that i'm going to place it just at the root of play that common i entity and let's also bring our a repository interface repository copy into play.com at the root okay so these two should have also the name spaces fix it so they're just going to be played that common so play that common that one and play that comment on this one let's also get rid of any needed namespaces like this one here get rid of that one and we're good now i'm going to add a new folder for our mongodb related classes so i'm going to create a new folder here and play that command called mongodb and in this folder we're going to add let's go back to catalog we're going to add the extensions file and the repository file copy those ones back in common mongodb paste so for these ones the namespace is going to be play that common that mongodb and on this one again play that common that mongodb i'll also remove any needed namespaces from here and from here and in the case of extensions we also need to tell it the new namespace for the settings files so i'll go to service settings ctrl dot and i'll use play that command.settings okay so now we have all of these common classes in our new common common project and that should be good to start building a new package but since we are here let's actually take advantage of the opportunity to expand a little bit our mongol repository class with a couple of new functions that our future microservices are going to be using for querying entities based on a filter so let's go ahead and go to our i repository interface so let's start here and what we're going to do is add a couple of new functions similar to our overloads to get all async and gate async but they are going to be able to receive an expression as a filter to filter which entities are going to be returned so let's start by get lsync i'm just going to copy this function i'll add a new one here and the way that we're going to specify the filter is going to be an expression a link expression so it's going to be an expression let's add a missing space link expressions and the signature we're going to use is the one that mongodb is expecting from us so it's going to be a func of type t so whichever type is the empty and bull filter okay so again so this is the way to specify a filter so that eventually when we want to retrieve uh entities based on some features let's say give me all the items that are owned by a specific user in the case of inventory and we will be able to use such a filter here so you can pass a query expression here and then mongodb will be able to to handle that filter and return the correct items for us the same way that we did that let's do go ahead and do get async another overload that is also going to receive expression so in this case you don't need to specify just an id to get one item or one one entity but you can specify a filter to retrieve any entity that matches that filter yeah and when we get to our new microservice our emitter microservice will see how both of these functions can be used so now that we have that in the in the interface let's now go to repository and actually implement these new methods so i'll go ahead and click on a repository ctrl dot implement interface so that brings in our new methods at the bottom i'm just going to relocate them next to their other overloads just to keep them close to each other so put that there i'll grab get async and i'll put it next to our other get async overload there and really this is very straightforward so what i'll do is i'll copy the the last line of our other uh sorry other get all async method i've got here this line and i'll copy it to our new get a license overload and really the only thing that we have to do is pass the filter there because let's see if you go to find you're going to see that it it can expect it can receive a filter definition but then in another overload it can actually receive an expression of the type that we have defined so that's if that's the overload that we're going to be using from mongodb to be able to filter so i'm just going to pass the filter here and i'm going to make this method also async that will be enough to retrieve all the items based on the filter and for the other overload they get async again i'll copy the code from the other overload over here and here the filter is already there so it's ready to receive the filter but let's make it async and that that will do it so we can receive one one entity based on certified filter and like i said these methods are going to be very handy as we move to the future microservices so with that done let's go ahead and build everything make sure everything is built in correctly so i'll do ctrl shift p okay so everything builds just fine and what i'll do now is i'll switch to my powershell terminal so that we can create this nugget package and how do you create a nuget package very straightforward you just use dotnet cli with the netback operation so we will do and then you have specified the output directory with dash o and then given my current file structure what i would like to do is to place the package in a packages directory under the d projects folder so what i'll do is dash o slash i'll go up three directories and then i'll specify packages slash and that should be enough hit enter and that's it the nuget package has been created under the packages and we can confirm that by going to here we have a packages directory now and if i go to packages the package is right here so this package contains everything compiled out of our play.com library so now it's time to go back to catalog and start using this new nougat package so i'll switch to catalog here we are and before we can get a reference to that to our play.com nugget package from catalog there are two things that we have to do the first one is to specify a nougat a package source for recurring nougat installation so remember that nuget packages can live in multiple locations they could live somewhere in your internet they could live somewhere in the cloud in a public location like doggy.org or in a private feed library private feed sorry or or they could live in your local machine as it is our case but nougat doesn't know about that so you have to tell your nugget installation which are the possible package sources where it can find the nugget packages so we're going to tell it right now that our nugget packages are in our d a pack the project package location so to do that i'll open our terminal right here what i'll do is i'll use again.cli with the dot net nougat command but then do get add search and here's i have to specify the location of my packages so in my case that's going to be the projects packages and then i'll give it a name n uh just to have like two for easier of reference i'll name it play economy okay so it's been added successfully and just make sure that you update this this location depending on where you send your packages in the in the previous step the next thing i'd like to do and i'll collapse this a bit is to go to our plate catalog service cs prog and what i'm doing is i'd like to remove this mongodb driver reference because now everything mongodb is actually referenced and brought in via the nougat package so we will not need to have an explicit reference to mongodb driver here i'll just remove that and now save this project and now we can go ahead and add our play.com reference so to do that let me switch to src let's go to play that catalog service and then we can do dot net add package play that common enter and the reference has been added as you can see right here so with that it is time to start cleaning up things so i'll go ahead and close my terminal and i'll close this and a bunch of things that we can remove now are the identity interface you can remove our entire repositories directory can be removed and our settings directory can also be removed okay so now it's time to fix our our imports so let's go to item cs and make sure it can find that identity now leaves under play.com from nuget package in our controller also the irrepository interface now is coming from play.common and we'll remove this old namespace and finally in startup let's get rid of these all namespaces exactly clean up the entire thing i remove all new desired usings and service settings is now going to be coming from play.com on that settings also our addmongo extension method is also coming now from play.com.mongodb and that's what it is so we are now completely using our nuget package i'll make sure everything is built in via control shift p yep it's building just fine and now let's test if the if the service is running properly so i'll do f5 to run our service and i'll go to postman and i'll just go ahead and do a simple query for all the items in the database via our items operation in the res api i'll hit send and here we are we are retrieving items from the database so everything is working properly so it works just as before but now as you can see our uh and i'll just stop this our code base is much simpler so we don't have the i i entered this interface here we don't have the repositories folder we don't have the settings folder anymore and yeah our startup looks very clean and so this is going to help us a lot for the construction of our future microservices in the next lesson we will learn about docker compose and how it can help us simplify the way we configure and start our infrastructure services in this lesson we will learn about docker compose and how it can help us simplify the way we run our infrastructure services we already started using docker to run our mongodb database and we are doing this via simple docker run command however starting with the next model we will need to start bringing in many other infrastructure services to support our microservices for instance in the next model we will use ravidmq as our meshes broker and in future models we will choose sec prometheus and grafana to enable a series of observability related components so if we keep just using docker run to execute our infrastructure services we will have to perform too many steps to setup them and we will need to remember too many arguments for each of them like the right environment variables ports and volumes also some of our containers might need to talk to each other like grafana and prometheus and some of them might not be able to work at all without another container be up and running first which again is the case of grafana which won't be able to do much without prometheus being available first that's where docker compose come into play compose is a tool for defining and running multi-container docker applications we will now be able to define all of our infrastructure services in a single file called the door compose jaml file this will include the definition of the container to use in each case environment variables ports and even dependencies between them then we will execute a single docker compose up command and all the containers will start in the right order with the correct configurations also compose provides a default network that all containers are joined to in case they need to talk to each other so with docker compose we are able to document the way to configure all of our infrastructure services in a single file and we get to start all of them with just one line as opposed to multiple commands also they all join a default network in the next lesson we will create our docker compose file and move our current mongodb configuration over there before we start using docker compose let's first create a new directory where we can place the compose jaml file and any future infrastructure related files so here i am in a new visual studio code instance i have opened my terminal and i am switch it into the project directory so this directory i'm going to create a new folder i'm going to call it play.infra and now i'm going to open in the visual studio code and the first thing that i like to do here is to take advantage of the another extension for visual code which is the docker extension which we can find if we go to extensions this type docker this one here because this one is going to provide us some good recommendations as we start working in our docker compose file so i'm going to install this extension click install and that will show up a new icon on the left side docker so let's close this and let's go back to our explorer now we can do is just go back here and let's create a new file let's call it docker compose.java and before writing any code here what i'd like to do is to bring in that previous docker run command line that we've been using just to keep it as a reference as we start writing this docker compose file okay you remember this this line that i just pasted this is what we've been using so far to kick off our or container so the first thing that you want to do in this docker compose file is to define a version for it the version determines what features you're going to have available in docker compose because different versions of the token compose engine support different versions so you have to define what version is this file for so i'll say version it's going to be 3.8 is the last one the latest one available as i'm recording this lesson and the next section is what we call services the services will determine each of these services is really one of our docker containers so i'll define a services section and under services you want to define our first service which is in our case is going to be mongodb so i'll just name it one go and as i start as i start writing this uh notice the indentation that i'm setting between each of these elements indentation is important because it defines which elements go inside other elements uh but to make this more uh more easier to see for you what i'll do is i'll enable another setting because to the code so we can see the white spaces that are happening across across the place so i'll go to file preferences settings and i'll look for render white space yeah so it's this one here so i'll switch from selection into all then i'll close this and now we can see the white space right there yeah so as you work on this file just make sure that you're leaving the same amount of white spaces or indentation with different elements that we're going to write i will also collapse this left side the navigation pane since we don't need it for now so we can have more space so inside the element we're going to open yet another element we have to define the properties for this for this service so first thing we're going to define is the image and as you remember from the command line on the top the image is so i'll grab that then we have to give a name to this to this container so the container is going to start up so i'll say container name and the name that we've been giving over here is so let's use the same name it's going to be the next thing is the ports so for sports is actually an array of ports so the rate you can define by placing a dash first and then you specify the port mapping so i'll grab that port mapping from here as you remember port is 27017 external port on the left side internal port on the right side and the next thing we have to define is a section for our volumes because remember that we need to map uh the slash data slash db directory inside the db container into a location outside of the host where the files are actually going to be written that's what we call a volume so to define volumes i'm going to go all the way here at the same level as our services section over there here we're going to declare a section called volumes and under volumes i'm going to define our mongodb data section which i'm actually going to copy over here one go to data column and that's really all you have to do to define a one volume uh in your in your machine and now we have to associate that volume to our service over there so i'm going to open yet another section here called volumes under ports and under volumes you have to define an array of all the volumes that you want for this service so the race starts with dash and then you define that that modeling mapping so i'm going to copy this again there so that defines that yeah so slash data slash db is mapped into mongodb data remember that we have to do this because otherwise our database files will be lost if we restart the container so from here on any time that the mongodb container tries to write to slash data slash db those files are actually going to be written into the mongodb data volume that's outside of the of the container and into a host machine okay so now i'll save this file and it's time to start running this a container via docker compose so i'll open my terminal ctrl j and the first thing i'd like to do here is make sure that i am not running mongodb container already so let's see wps docker ps and yeah so we are indeed running it already we don't want to have it running there because that could cause conflicts so i'll just go ahead and stop it docker stop monko okay and now uh it has been stopped so with that done we can go ahead and start our docker a container video via docker compose and we can do docker compose up hit enter and then that starts running the container and what you're seeing now is just the output of the mongodb container being generated directly into the terminal so now that we have the docker compose a docker composer running our dock our mongodb docker container uh let's see how is our catalog api working with this a new new way of running the container so i'm going to go back to uh to our catalog microservice and i'm just going to hit f5 to get things started okay with the host up and running let's go ahead and open postman and let's go ahead and try to get our old items in the database so here i am in my get operation for the rest api so i'll hit send and interestingly i'm not getting any items which is interesting because the as per our previous lessons we did have at least one item um already stored in the database so what's going on let's see uh let's go back quickly to visual studio code catalog and let's let's explore our database at this point in time so i'll collapse this a little bit and let's go to the mongodb extension and here's a localhost 27017 i'll connect to it and the interesting piece here and i'll collapse these other pieces is that we don't have a catalog database anymore and this is happening because as we are started as we moved into docker compose a new volume has been created for our database files so technically this is a brand new database which has no items yet right so there's actually nothing in there so there has not been any need to create the database yet so that's why you don't see any database here so just keep that in mind as you switch from a raw docker execution into torque compose a new volume will be created so let's actually come up with something for our catalog database so i'll go back to postman and i'll go to my post tab body okay and so let's again define something here we'll go again to our potion example so it's a potion and it stores a small amount of hp and the price is going to be just 5. so go ahead and send this and the item has been created if we go back to our get items api once again hit send the item is there and if you go back to visual studio code to catalog and we've refreshed this you can see that now we have our catalog database with our items collection and the one document already created in there and one last tip that i want to give you as you start working with docker compose is how to prevent let me actually open docker compose how to prevent all this uh output to be shown here so in case i don't want to see all this output from the database all the time uh you can see things in a much cleaner way by doing the following so i'll go back here to my terminal i'll just hit ctrl c to stop docker compose and what you can do is you can do docker compose app but you can append the dash d a parameter to run in detach mode so if i do enter now the only that you're going to see is that it's starting and then it says done so the container is running in the background but you don't have to be looking at all the output all the time so you're running in a detached mode and still if you go back to postman and you query you can see that the container is actually running so we have reached the end of this model with a few improvements to our developer workflow and with a reusable library that will speed up the construction of our future microservices in the next module we will introduce our second microservice and we will learn about the multiple challenges of having microservices talk to each other in this model you will learn about the different microservice communication styles and then you will learn about a few techniques to properly implement synchronous inter-service communication between the existing catalog service and a new inventory service by the end of this model you will have a solid understanding of the following the different microservice communication styles how to implement synchronous communication between two services via rest and the http protocol what kind of partial failures could impact your mega services and why you should design for them how to set timeouts to fail fast when doing inter-service communication what is and how to implement the retries with exponential back-off technique and when to use and how to implement the circuit breaker pattern in this lesson we will create our inventory microservice which owns the player's inventory of purchase items just like we did with the catalog service we will define a rest api for inventory with a couple of operations which are both items which will be used to add an item to the player's inventory back and get items by user id which should retrieve all the items for the specified player or user talking about users you may have noticed that we have not properly introduced the concept of players or in general users into our system this is fine the management of the actual users database will be the responsibility of the identity service which will be we will create in a future model along with all the microservices security infrastructure for now we will choose random guides to identify the users that own the inventory items let's get started let's create our inventory microservice i have started by opening a new piece of studio called instance i have opened my terminal and i have switched to the project directory so i'll create a brand new directory for this new microservice so let's call it play that inventory and then let's switch to that directory in the terminal and then what i'll do is i'll use this command line to ask the current instance of visual studio code to open this new folder so i'll just do code that for the current directory and then i'll do dash r to reuse the green window so i'll hit enter that will be the equivalent to or we use the file open folder and menu but it's much faster now i'll create as usual our source directory and in that one i'll right click i'll say open integrated terminal to open a new terminal in that location and then i'll go ahead and use dot net cli to create the new project so.net new web api dash n play dot inventory dot service is going to be the name okay so that generates a bunch of files on the left side and i'll i'll get the omnishar server started by clicking on any of rc chart files so i'll click there that kicks in on the chart server and that prompts us to add the the test.json and logistics.json files so that this will code can build and debug our project so i'll say yes that adds our files on the left side over here and then i'll go right away to our task.json file to add our group section where we can say that this is the section that by default builds the project save that okay so now also close our terminal for now and then i'll go to launch.json and i will remove this section just like we did with catalog so that anytime we start the server it doesn't open up web browser by default i'll just remove that and what i'll do next is i'll go to uh under properties i'll go to launch settings.json because we want to specify which is going to be the ports that we're going to use for inventory so remember we are already using the default ports for catalog 5001 500 and 5000 so we have to use new ports for inventory they cannot be the same port so i'll use i'll go for 5005 and 5004 for our https and http ports for inventory you could use any other port really here as long as they are not being used by any other application in your your computer next i'll go ahead and i'll delete what we don't need from these projects i'll delete weather forecast controller and i'll delete the weather forecast class over here so now i'll get started by creating our details so the dtos that are going to be used by our controller class and their arrest api so just like we did before i already click in play inventory service i'll say new file i'll create dtos.cs here i'll declare our namespace the namespace is going to be play.inventory.service.dps and so we're going to define two dtos at this point the first one is going to be the dto used to grant items to a user and the other one is going to be the dto used to return the series of items that a user already has in their inventory so let's start by defining public record grant items video and to grant the knight into a user we obviously obviously need to specify the id of the user so it's going to be a good user id let's add the system in space there we also have to specify which is the item the catalog item that's going to be assigned so we will define that as catalog item id and lastly we have to specify how much of the item is going to be assigned to the user so that's going to be the quantity let's notify the other the other dto as public record this is going to be inventory item dto like i said this is the dto used to return items the items that are assigned to a user and the user's inventory so for this we're going to be returning the catalog item id the quantity and also let's define the the acquired date so this is the date when the item was a was put into the user's inventory so now that we have our details it is time to start defining the entities that we're going to be using to store inventory items into the database however before we can do that uh we have to bring in the our play.com nugget package so that we can start using the the bunch of classes and types that we have defined there including our i items our intt interface so to do that i'll go ahead and do ctrl j to open my terminal and i'll go to late that inventory service and then i'll just do net add package play that common okay so if you go now to play men3 service we'll see that we have the nuget package added here now we can go ahead and right click in play inventory service new folder entities and let's go ahead and define a new file it's going to be inventory item dot cs let's define our namespace it's going to be play.inventory service entities let's define the class public class inventory item and let's make this class right away implement our i i entity interface let's make it use play.com into a namespace and as we're implementing that interface let's do ctrl dot implement interface so we have to define a good so probably good id we'll make it define just a get we will use a get and set just like that okay so each metal item will have an id then it should have it should know to which user it belongs to so let's do probe good it's going to be user id next let's define which catalog item this inventory item corresponds to a reference to the catalog item so it's going to be prop good catalog item id next we'll define the quantity it's going to be the quantity how much of this item we have let me also close this terminal now and lastly let's define the time of set is going to be the acquired date the day when the item was assigned to the user in the inventory save that and just like we did with catalog let's define an extension method so that we can transform one of these inventory items into the inventory item dto so i go ahead to the root play inventory service i'll add a new file i'll call it extensions let's add an a space play that inventory that service and let's add public static class extensions and let's define our method here so public static is going to return an inventory item video let's call it sdto and let's import a missing namespace and it is going to be extending inventory item into the item let's import that it's going to be the item and here it is just about creating a brand new item dto out of this item so we will say return new inventory item dto with item dot catalog item id item dot quantity and item that acquire date so that's all we have to do to transform the item entity into an identity now we can go ahead and create our controller so let's go to the controllers folder right click new file we'll name it items controller just like we did in catalog let's define the namespace for it play inventory service controllers it's going to be public class items controller and remember each of our itunes controllers should be a mark with the api controller attribute it should derive from controller base and it should define the base route that is going to be a map2 so route this route just like with catalog is also going to be items just because it also manages items so route items so now we're going to need a one class level variable here which is going to be the repository that we're going to be using to store and retrieve items so let's define private read-only it's going to be a repository of type inventory item and let's just name it items repository so let's import play common here and let's import play inventory service entities let's also collapse this navigation pane for now since we are not going to be using it for a bit and now we have to do dependence injection to actually receive this items repository into the controller so let's define a constructor okay so this constructor is going to receive again our i our repository so just copy that here item repository and let's assign it to our local instance hide the repository so now it's time to define our two operations here we need an operation to get all the items in the inventory and one operation to put an item or to create an item into the inventory so let's start with the get operation let's define that as public async task of action result and this is going to be of an innumerable of inventory iron detail and then we'll name it just get async get async and the parameter is going to be the user id so we want to get all the items in a user's inventory so we're going to receive good user id okay let's see let's add any missing spaces 3d tasks systems collection generic and service ctos and for the guide using system let's also define the verb that is associated to this api which is going to be http get and so the way that this api is going to where this operation is going to work is we just need to go ahead and get all the items based on the user so but before we can do that let's do a quick check let's make sure that this user id is not empty so if it is a good empty we are going to return a bad request request a simple validation in there and so to get the items we're going to do this so we'll say so the items is going to be and we're going to open up braces here we're going to do a sink call to items repository get all the sync and here's where we can start using our expression our filter based on an expression so in this case what we want to say is that we want to get any item where item.user id equals the user id that we got as a parameter over here okay so that's that's how we can filter items based on a user in this case and then when we have that we can do a select and let's see if we're missing another namespace system link where we're going to specify that we want to take each of these items that we found in the database and transform them as into a dto with our extension method and finally we'll go ahead and just say return return the items let's also transform this let's just wrap this into the ok into the k action result and that's all we have to do so that will return all the items in the user's inventory the next method is the one that we're going to use to assign one item to the inventory this is going to be a post operation so let's see let's define it as publication task we will just do action result we're not returning really anything out of this method i'm going to impose async and it's going to be receiving our grand ideas dto at istio let's mark this with the http post verb here we're going to do is we will try to find the if we have that inventory item already assigned in inventory because it could already have it so in which case we just need to increase the quantity or in the other case when we don't have it we just have to create it for the first time in inventory so let's try to find it so we'll do so it's going to be inventory item equals await items repository get a sync and again here's where we can use the expression filter where we're going to say that the item that we're going to try to find has to be one where the item that user id has to match the grand item cto user id and also the item that catalog item id has to match grant identity to your catalog item id let me see if i can put this in the next line so that will find the item if it is there so but if the inventory item happens to be new it is this is the first time that we assign this item to the user so in that case we will go ahead and say inventory item equals new inventory item and we will set its catalog item id is grant items dto.cattleguardian id the user id is grab itemcto.userid the quantity is that quantity and for acquired date we will just set our current date time offset so it's going to be daytimeoffset.utc.now and finally we will call our method in items repository to create an item so create a sync inventory item okay let's add this missing using semicolon there and then let's go for the other branch so else we did find the item so we just need to increase the quantity so for that we will do inventory item.quantity plus equals itemcto.quantity and then we will do weight itemrepository.updatesync with the inventory item and finally we will just return we'll just return okay and that's pretty much for the a controller operation so we have two two operations to retrieve the items in inventory and to put an item into the inventory so with that done it is time to start doing the basic uh configuration of a startup so i'll go back to our explorer here and first let's go to websites.json here we have to define uh the settings for our in order to define the service name and the mongodb a mongodb connection so to save time what i'll do is i'll go back to catalog actually and i'll open my app sizing json file over there and i'll just copy these two sections from the app statistic json i'll go back to inventory and i'll paste that right here really the main thing the only thing that we have to change here is that this is not the catalog service anymore this is the inventory service remember that this is what's going to define the name of the database that's going to be created in in mongodb save that and now i'm going to want to go to startup i'll actually clean up a bit disney spaces so i'll do control dot here remove necessary usings and now i'll go to the start of configure services and i'll add the services for mongodb and the repository so i'll do services that add and that may need another import pay common mongodb and then i'll add a repository of type inventory item let's add a using there and here we have to specify the name of the collection here so the name that we're going to give it is inventory inventory items save that and so with that we have registered everything related to mongodb and we actually are ready to start trying out this microservice so i'll go ahead and hit f5 okay and then what i like to do is actually import the the specification cover api into postman to make our lives a bit easier what i'll do is i'll copy a copied url of our service localhost 5005 and then i'll go to our browser just for this time paste that there and then let's go to slugger so this defines as you can see this is the soccer ui page for our rest api then i'll click in the swagger.json link here and i'll copy that copy that and then i'll just close this browser now i'll go to postman and here what i'll do is i'll just click on import link i'll paste that click continue and i'll just say import so now if we go to collections we have now not just a catalog service section but also a collection but also a plain inventory service collection with our two items related operations so what i'd like to do is to go ahead and post and try out our post to assign an item to a user but of course before that we have to define the base url for our for this collection so let's go to dot let's go to edit variables and in this case our base url is as remember let's go to inventory base url is localhost 5005. put that here i'll put it for current value and for initial value update that okay so it knows the base url now being imposed we go to body and here's the three things that we need user id catalog item and quantity now for user id um like i said in the introduction we don't uh we don't have actual users so far so we just generate a random one and one handy way that we can do that in postman is by using the coolid function that's built into postman so what you can do is just this so open two sets of curly braces and then you're going to do just good so that will on the fly generator quit for us and for the catalog item id we want to know the id of one of our items in the catalog so to do that let's actually query our catalog items but before doing that let's go back to catalog and just hit f5 to actually start the web server so that we can query the catalog and then i'll go back to postman into our play catalog service collection i'll expand this i'll go to get items and i'll just hit send and here is the one item that we have the catalog the potion so i'll copy this id and i'll go back to our post operation paste it there and let's say that we want to assign just one one of these potion into the user's inventory so now go ahead and hit send and we got 200 okay meaning it was a success and so to verify that this actually worked let's actually try out our get all items in inventory operation so i'll click on this new operation and in this case the first thing that we're going to need is uh to specify the which is the user id right so which user was that item assigned to which we if you go back to post it was an automatic automatically generated users we actually don't know yet but we can figure that out via our console so i'll click on the console down here and you open the post operation and we expand the body the request body you see the user id is right here so this the console records everything that's going on behind the scenes so it's pretty handy in this case so i'll just copy the user id and i'll close this then i'll go back to our get items from the inventory service and i'll paste that right here so with that i'll go ahead and hit send and here it is so this user has a one of the catalog item of this id and with this acquired date where the date was assigned and so let's say that we wanted to increase the quantity of that item for this user and we want to actually test this this other codepath so let's go back to post body and let's say that we want to add uh perhaps four more uh potions to these users inventory so i'll just do that uh we want to change now we don't want to generate get another good so replace user id with the id that we we just copied for our user so then i'll go ahead and hit send 200 okay and then if we get items for this user in inventory i'll hit send and now the quantity is five so now the user has five items in his inventory okay so at this point our inventory service can store and report the items that each user has in his inventory back however notice that this dto that we have returned by the get operation only provides the ids of the items in the user inventory so since we don't have any names of descriptions it is a bit hard to tell which items are in the user inventory which are the actually so what does 4e 9c means really so in the next lesson we will learn about microservice communication styles and how our inventory service can use them to retrieve more details about each of these items from the catalog service in this lesson we will learn about the different microservice communication styles and how to implement the synchronous communication style vrs and the http protocol there are basically two ways you can communicate with microservices the synchronous style where the client sends a request and waits for a response from the service and the asynchronous style where the client sends a request to the service but the response if there's any response will not be sent immediately so far we have been using the synchronous communication style when interacting with our services via swagger ui and postman and in this lesson we will explore how to use it for inter-service communication we will learn about the asynchronous communication style in a future lesson when using the synchronous communication style the client sends a request and waits for a response from the service which means that the client cannot proceed without a response you may make this more evident with any of our services if you put a breakpoint in one of our service controller actions like get async in the catalog items controller start a debug session in bs code and then try sending a get request to it be a postman you will notice that postman waits indefinitely for our service to respond it can continue until the service responds many times this type of communication uses a blocking threat meaning that the client is unable to receive any other inputs or perform any other task until the response arrives but it could also use an unblocking thread where the client just offers a callback method to the service so the service can call the client back when the response is available in this case the client thread does not block even when it still waits for response there are two approaches currently to use the synchronous configuration style rest with the http protocol which is a traditional approach and the one that we have been using so far in res the business objects are modeled as resources and http verbs are used to manipulate them also you usually use xml or json to represent the resources most clients support rest the other approach is grpc which is a binary message-based protocol in which clients and servers exchange messages in the protocol buffers format grpc is becoming increasingly popular because it supports http 2 and is more efficient addressed however not all clients support http 2 which is why in a microservices architecture grpc is used mostly internally between the api gateway and the services or between the services in the next lesson we will be implementing synchronous communication between catalog and inventory microservices using rest and http at this point when the client requests the items inventory back for a user the inventory service creates its database and retrieves an array that has basic info about each item including the catalog item id and the quantity however having a list of item ids does not tell much to our client in terms of what actual items the user has on inventory ideally we would like to get at least the name of each item and hopefully also a subscription however inventory doesn't know such details about the items since the information is owned by the catalog service one way to address this is to have the inventory service send a get request to the catalog service to retrieve the details of all the items inventory can then combine this additional info with the details it has in its own database to send back the decided more detailed payload to the client let's go ahead and implement this approach our inventory microservice needs to receive data from the catalog microservice but before we can do that it first needs to define the dto that represents the retrieved catalog items now it turns to be that we already have such a dto that represents catalog items and if we go to our catalog project our catalog microservice and if we go to dtos.cs we're going to see that such d2 is right here so this is the dto item dto that represents cattle guidance when you query for them so what i'll do is i'll just copy this dto copy this and then i'll go to inventory here we are in inventory and i'll open dto.cs and i'm just going to paste that as initial dto for uh for the inventory and the case of inventory we're going to rename this into catalog item detail just do not confuse it with inventory attended to you and uh for example inventory again uh we don't need that many properties when we're querying for catalog items and you don't have to retrieve everything or at least digitalize everything into inventory the only thing that we're going to need in this case is the id of the item the name and the description we don't need price and created date for our purposes so remove those save this and now that we have this dto we can actually build a client that is going to be able to query for this item from catalog so i'm going to right click in play inventory service i'll create a new folder let's call it clients and in this one i'm going to create a new file that i'm going to name catalog client that's cs let's give it a namespace display inventory service clients public class catalog client so in order for our catalog client to be able to talk to any external http endpoint it needs to use the net http client class so we're going to define that as a class level variable here private read-only http client http client and i'll import the system.http in space and now we're going to do dependency injection of this client into our class so public catalog client http client and we'll take that reference now that we have that client available we're going to define the function that's going to retrieve actually retrieve the items from catalog so this is going to be an async function so let's define it as asynctask and what we're going to return is a collection of catalog item dto since the the consumer is not expected to modify this collection in any way we're just going to return a read-only collection of type catalog item dto and we'll name it get catalog items async let's import missing spaces for tasks and forbid on the collection and for catalog item video to retrieve the items we can do that really easily with one line so we'll do items equals weight http client get from json let's change this get from json async we need to import another space system http json and we'll um will deserialize as i read only collection of type catalog item video and then here is where you put the route that you want to access in the invoked address api in our case in the cases of catalog the route would be under items and with that we can go ahead and return return the items that's all you have to do to invoke another a recipe i in another service with that done it is time to update our inventory identity to have this additional information that we're going to collect from catalog so let's go back to dtos and inventory item dto we're going to add a name and a description but as we do that and as we can see extension is complaining and it's because we need to provide that additional additional uh members to the construction of inventory in dtu as we transform the inventory item entities so what we'll do is we're going to receive additional parameters into this method which are going to be the name and the description [Music] and we'll fit those two into inventory item dto constructor there with that done we are ready to go to our controller to actually take advantage of this new this new information so i'll go to items controller and the first thing that i'll do is i'll get a reference while defining a classless variable for our catalog client so i'll define private read-only catalog client capital client okay let's import the missing space and let's receive that as a penis injection into items controller i receive the catalog client and we'll get the reference and now that we have that let's change a little bit how we do the our get async method so we'll get rid of these lines for now and the first thing that we're going to do is to actually retrieve the catalog items so how do we get the catalog items very easily now we can do catalog items equals weight cattle client that get catalytic items async that's all it is okay so that gives us all the catalog items in the catalogs microservice now we want to get the list of all the inventory items that we have currently in the inventory microservice so we'll do that via inventory item entities it's going to be await item repository get all these sync where the item item that user id equals the user id that we got as a parameter okay so now we have all the catalog items and then we have all the entities the inventory item entities for the current user now we need to combine these two pieces of information to produce the dto that we want to return so to do that we'll do this so inventory item dtos equals inventory item entities select so we're going to do a projection here for each inventory item [Music] we will do this let me close that first we will look into the collection of catalog items and we will find the catalog item that corresponds to the current inventory item so catalog item equals catalog items that's single there should be one and only one catalog item where the catalog item catalog item that id should match exactly the inventory item that catalog item id and once we have that we can do the conversion of the inventory item into a dto so we will do enter the item return inventory item as dto and then we have to provide the catalog item that name and the catalog item that description and finally now that we have the inventory identities we will return those as opposed to these old items collection so inventory item details so our catalasing method is ready to retrieve an improved set of items with name and description and now it is time to do the proper registration in a startup to let our application know about this new catalog client that we're going to be using let's go to startup and what i'll do is i'll open a little section just under our registration so i'll do services dot add http client and alt line is going to be catalog client let's import missing a space and then i'll receive a specifier parameter here is going to be the client okay let's open that expression there and here really the only thing that we have to specify for now is the the base address of this automaker because otherwise how how would it know so we're going to say that the client base address equals a uri let's import a missing space and then if you remember the uri where our catalog microservice leaks so far is a localhost 5001 so that's what you have specified here https localhost 5001. okay so this is a handy way to register our catalog client so that it can be used by dependency injection in other classes like in the controller right so you say http client catalog client and then you specify the base address and then when that client is instantiated it will automatically receive an instance of the http client that you're going to be using to query four items okay so with that done let's go ahead and hit f5 let's see this in action let's not forget to also do an f5 in our catalogue service so i'll go ahead and start also here's catalog i'll start it f5 and with the two service up and running we can go ahead and go to postman here in postman i am already in the in the tab for the operation that can retrieve all the inventory items for specified user id so this is user data we've used in the previous lesson uh so let's see what information we can get now that we created the api so we'll go ahead and hit send and as you can see we are able to retrieve the catalog item but this time we not just have the id of the item we also have the name and the description of the catalog okay so this seems to be working pretty well however think about what will happen if the catalog service started having issues at least temporarily but what happens if it's completely down in the next lesson we will learn about the problems that we might find when having a service communicate with another service in this lesson we will learn about partial failures in microservices and how to deal with them using timeouts and the exponential back-off technique even after placing our best efforts to ensure we have a healthy system it is a matter of fact that in distributed systems partial failures will happen this could be due to multiple reasons including network outages hardware failures dependency failures and even routine things like having a deployment in progress regardless of the cause of the partial failure when calling a dependent service it could certainly cause our microservice to fail which will end up in a bad experience for our clients so whenever a service makes a synchronous request to another service there is an ever present risk of partial failures and so you must assign your service to be resilient to them one of the first things to consider when making requests to dependent service is setting appropriate timeouts a service client should be designed not to block infinitely and use timeouts think about the experience of our client when the catalog service takes a long time to come back to our inventory service if it ever comes back now the inventory service is also taking forever to respond to the client leaving our users with a bad experience and not only that at least one of the threads of inventory is now busy not being able to serve any other requests which reduces the amount of available resources in the service instead of this you can set a timeout of say no more than one second so that if catalog service takes more than that to respond the request immediately fails and the inventory service can in turn return the appropriate request to the client even if it's a failure this enables a more responsive experience and also ensures that resources are never tied up indefinitely like we mentioned it is not uncommon for transit failures to occur in a distributed environment therefore you usually want to give the dependent service one more chance to come back with a successful reply however you don't want to keep retraining at a constant rate since that could overwhelm the dependency a good strategy that you can use for retries is the one called retries with exponential back off this strategy performs call retries a certain amount of times with a longer wait between each retry and here's how it works as usual the client will make a request to our service and this one in turn will make a request to its dependent service if this second request fails instead of failing right away our service will wait some time and then it will try again if the request fails again we will now wait a longer amount of time before trying the request if it keeps failing we will wait a yet longer amount of time before one more try and eventually if we have tried enough times with no successful response we will let the call fail as you see this strategy lets the failing dependency have an increasing amount of time to recover it also avoids overwhelming the dependency let's see how to implement timeouts and retries with exponential back off in our inventory microservice let's see our inventory and catalog microservices in action once again so here i am in catalog and i'll just hit f5 to start a web server and then i'll go to inventory and i'll do the same thing hit f5 and now i'll go to postman and i'll try to get all the inventory items for this user id so i'll just go ahead and hit send and here's what we expected to get right so the list of inventory items with them and description now to simulate the effects of partial failures let's first add a few temporal modifications to our get out items operations in catalog microservice so i'll go to our catalog visual studio code instance and i'll stop it for now close terminal and i'll go to items controller and what i'll do is i'll modify or get async method the one that retrieves all the items so that it introduces a few temporal failures uh for our inventory client so before doing that i'm going to add a little uh a little variable to track how many requests we have received from the from the client at this point so i'll just add private static in i'm making it static so that it doesn't reset after every request let's just call it request counter start with zero and now in get a scene i'm going to open space here let's go down and i'll do the following first thing that i'll do is i'll just increase the counter and then let's add a lock line just after this console.the right line [Music] i will just say string interpolation request request discounter starting so that's that's why it tells us that it's starting a new request then what we're going to do is for the first two requests we will actually increase i mean we'll add a delay to simulate the timeout scenarios so if request counter less than or equals to two we're going to say i'm going to copy this line here console.writeline we will say delaying and i'm going to say wait that's that delay this is how you can introduce a delay in the current request in an asynchronous way time span that frame seconds will say 10 seconds so the first request will be delayed 10 seconds then i'll copy this block here down here and we will say that if the request counter is less than or equals to four what we're going to do is just return an internal server error right so three to to simulate that kind of error so request request counter we will say 500 internal server error and we will return status code 500 now at this point we are introducing this capability of uh returning either one result here or another type of result here and in order to do that uh remember that we have to switch from just returning the innumerable into returning an actual i actually result so i'll say action result of a numerable of identity and i'll close this so that gives us ability to return more than one type of a result and also we'll have to modify our final return clause here so that it returns something that can be mapped to afghanistan like the okay result and lastly what we're going to add here just over here let me copy this console right line this is going to be the happy path where we finally return something and we're going to say resquez request counter we will just say 200 okay okay so for a quick review we have a static request counter so every time a request comes in it increases the counter uh the first two requests are going to have a 10 second delay the next two requests are going to end up in a 500 error and then if we get get past that we'll get at 200 okay and so at this point i'll go back to our inventory this is our inventory i've used to call instance i'll just stop it close and what i'll do is i'll first go ahead and collapse our navigation pane for now i'll open my terminal over here i'll open a new partial terminal what i'd like to do is actually have two terminals in this window so we can see the interactions between microservices so i'll use the split terminal icon here to open a second terminal and in this one i'll actually switch back to play that the catalog directory okay play the catalog service and here i'll do dot net run so that we can see the outputs that are coming out of catalog and then on the left side i'll start up our inventory microservice same way i'll do that run okay so with that done let me go back to postman and i'll try the query once again so i'll hit send and back in bs code you can see that now this first request is getting delayed and now our inventory client is experienced experiencing this significant timeout if we try it again for the point of views postman so look at this it just keeps waiting waiting and waiting we're giving a really bad experience to to our clients right okay so what can we do about this so the first thing as we mentioned is to introduce a proper timeout to avoid this kind of situation so let's go back to visual code and what i'll do now is i'll stop both web servers so i'll go to my inventory turbine and i'll do ctrl c stop server catalog control c stop server and what i'd like to do now is to add our a reference to the poly nougat package so so this is the package that you can use in your.net applications to properly handle transient error failures in a very easy way so being in play inventory service i'll do net add package microsoft.next enter okay and then perhaps i'll put this back into place and then i'll just do ctrl j to hide all terminals for a moment then i'll go to our explorer and i'll go to startup.cs and i'll collapse this once again we don't need it and let's go into configure services and um yeah so let's find the section where we are adding the http client right here and here what we're going to do is we're going to append yet another call to another method here that's going to be that's called add policyhandler and uh here's where we can define a policy so paulie has this concept of policies that different policies that can be used to handle a different transient errors when you're invoking an external api so we're going to use policy and then let's import any missing space using poly so we will say policy dot timeout async and then we specify a type here and that type is going to be http response message and let's add the system.net namespace because this is the type of response i will get when you invoke the external external client so and uh in this parameter we'll specify uh how many seconds we want to wait maximum after calling an external api and before just failing so i'll say one second in our case and i'll close this so just by doing this you're saying that anytime we invoke anything under localhost 5001 we're going to wait at much one second before giving up so let's see now how this works i'll bring in back my terminals via ctrl j and then i'll do dot net run in both cases okay perhaps i'll move this a little bit to the right and then let's go to postman and try the request once again as you can see it now took just a little bit more than one second to complete the request so instead of waiting for all those 10 seconds wasting resources let's try again yep and once again it just took just a bit more than one second if we go back to postman we can also see we tried the two requests on the right side but then they usually took more time to respond but regardless we were already we had already failed on the on the left side on the inventory side so that would at least help us fail fast to avoid the long delay and avoid consuming inventory resources unnecessarily however we note that transient errors are not uncommon in distributed systems so we would like to not just fail right away but instead try a few times hoping for the catalog service recovery in the next lesson we will implement the retries with exponential back-off technique to improve our chances of succeeding in the presence of transient errors in the last lesson we introduced a one-second time-out policy to inventory microservice let's now use the retries with exponential back-off technique to let inventory retry the calls to catalogue a few times before giving up so here i am once again in the play the inventory microservice and here's a line where we last in last lesson we added our timeout policy what we want to do here is add yet another policy to specify what to do in the presence of transient errors and how to retry so now i'm going to be adding that policy handler right here just between the add http client call and the add policy handler call and just pay attention of the location of this because we want to make sure that we can combine the timeouts with the transient error hunting so that any time that we retry we actually wait just one second like specified in this policy we wait one second uh between tries if you don't do things in the order that are going to be shown here that combination is not going to work properly so at this location i'm going to say add transient http error policy and let's actually go into the definition of this method for one second so go to definition uh so so just so that you can see what this this method is handling so this method is taking care of network failures it's also taking care of 500 500 errors several errors and a 408 status quo so request time out so this method we're going to use is very handy so because it can handle all these situations by itself automatically i close this and again notice the location where i added this so now what i'll do is i'll say builder and then we'll say builder dot weight and retry async and here we're going to open parentheses and we need to specify a series of parameters for this policy and the first parameter is going to be the retry count so this is how many times we want to retry in the presence of transient error failures so for our case let's say we're going to go for five retries the next parameter is the sleep duration provider so this is just a function that determines how much time to wait between each retry so for this we're going to say we try attempt and then we'll use a time span class to specify a duration in seconds but here is where the exponential back-off part comes into place we are not going to just specify a one specific amount of seconds we are going to say but that pow so that we can say uh let's go for two and then we'll raise that into retry attempt so this means that every time we're going to wait we're going to be waiting an increasing amount of time that depends on the retry attempt so for like the first time it's going to take two raised t raise it into one the first which i attempt so two at one is going to be two so two seconds so next time it's going to be two a raise a two so it's going to be four seconds the next time eight seconds it will keep going that way in an exponential way so that every time we just wait a little bit more so that's that's a potential back-off piece of of this technique and then next we're going to specify yet another parameter uh that you don't really need it but we're going to use it just for the purposes of demonstrating what happens between the different uh the different calls so you can totally skip this if you want to if you want to don't want to see what's going on behind the scenes so i'm going to say on retry and then we specify three parameters it's going to be outcome a time span and we try attempt so i'll open this and then here we can specify um what we want to do each time that retry happens what we want to do is just present the lock a lock message in the console and we can do when you we can use i logger for this now uh uh to do that at this point we need to actually get an instance of the ilogger a lower class but uh we don't have a easy way to do that right now so what we're going to do is to as an instance of the service provider we're going to create a service provider and from that one we're going to get that service this is not ideal and that's actually going to present a warning message in the console but we're doing this just for demonstration purposes so totally avoid this this technique in production code so let's see we'll say service provider equals services dot build service provider and then we will say service provider that gets service we want an i logger of catalog client okay let's see if we're missing a namespace extension's logging okay so if you're able to get that that that service instance so we'll use this equal question mark there we'll say that log warning and here's where we're going to specify that message and the message is going to be and we'll do a string interpolation here we'll say lane for so many seconds and those seconds are going to come from time span the total seconds and then then making retry and that's going to be retry attempt okay close that save and one more thing that we have to do here is make sure that we combine both of these policies so that they can work together and to do that what we have to do is go back to this builder declaration here so where and then we have to say builder dot or and then we specify the exception that will be coming out of the timeout of the timeout async call over here so in that case that exception is going to be timeout rejected exception and then let's see if you're missing any space using polytimeout okay so that's how you can say that if the actual and then let's add missing parenthesis if we fail because of a timeout produced by the timeout policy then it will fire a timeout section let's go ahead and also retry okay so that's the right way to combine both policies okay so now let's just save this and i'll open my terminals and left side is inventory i'll do dot net run right side is catalog dot net run let's expand this a bit and notice the warning that i was mentioning before and this happens like i said because of the way that we are doing a the service provider construction here there's a radio service provided built in into the spinal cord of time we are creating a second one that's not ideal and but like i said it's used for demonstration purposes feel free to remove this section in your production code so now that we have both services up and running let's go back to postman and let's go ahead and do a send to see what happens so it starts and go back going back here you can see that uh first time we tried and then we waited two seconds then we waited four seconds then we waited eight seconds we're trying to wait eight seconds on the right side you can see that the multiple requests are coming in now they're firing internal server drivers and now we are in what's probably the last the last weight uh for 16 seconds and so the client in postman as you can see it just keeps waiting uh it's not it doesn't fail right away but we are trying to get a chance to actually succeed and yeah eventually that happened the client succeeded and we no longer see an error if we see back into postman we can see that yeah indeed eventually we go to 200 okay 200 okay for the last request and it is looking great now the one issue with this is that if you have multiple instances of your in this case our inventory service uh calling a catalog and they are all waiting exactly four seconds exactly eight seconds 16 seconds between the tries that can actually cause a kind of burst of of calls into catalog service at the very same time right because they are waiting for exactly the same time between retries so to avoid overwhelming our catalog service what we can do is introduce a little bit of randomness so that it is not exactly four seconds or exactly eight seconds and stuff like that so how can we do that i'll do ctrl c in both of my terminals to stop those processes and do ctrl j to close the terminals and what we're going to do is add what we call a jitter so this is going to be the way to add that randomness here so i'll go up and just over here i'll introduce a random error it's going to be new random and then let's go back to the section where we're defining the retry attempt over here and we're going to do is just go to next line and we will say plus time span that from milliseconds and we will say uh yearly dot next and so we want to add is some number of milliseconds to those seconds so we'll say any number from 0 to 1000 should be fine so this time we should see that it's not just a specific amount of seconds but those seconds plus some milliseconds that are going to be generated at random so i'll save that open terminals again ctrl j dot net run and dotnet run and let's go back to postman and try this again so i'll hit send let's go back here and as you can see now we are not waiting just two seconds but 2.5 to 3 seconds and the next time we're waiting for that 3-8 seconds and so on and so on yeah so with that the different instances will be invoking back to a client at different slightly different times which lets a catalog not get overwhelmed and so this is much better and would certainly help us handle temporal glitches uh when reaching out to the catalog service however imagine that a widespread network outage is preventing us from reaching catalog or perhaps is preventing catalog from reaching its defenses so such outage would likely last let's say a half an hour and if we have all of an inventory service threats retrying that much time we may end up exhausting its resources in the next lesson we will learn more about resource exhaustion and how to deal with it via the circuit breaker technique in this lesson we will learn about resource exhaustion in microservices and how to deal with it using the circuit breaker pattern having a retry policy in place is good but you also must be mindful about the limited resources available to your service imagine once again a situation where there is an ongoing issue with your service dependency this might not be just a transient issue but instead some prolonged downtime caused perhaps by a broad network now the client calls our service and this one in turn invokes the already failing dependency which will hopelessly start waiting for a reply while this is happening more clients keep sending requests to our service and this results in more requests being sent to the failing service one thing you have to realize is that each of these requests are making use of your service threads of which there is only a limited amount once enough threads are in use there are no more resources available and you can reach what we call resource exhaustion when this happens your entire service becomes unavailable for any future requests potentially causing a lot of trouble in the system one approach we can use to properly handle this issue is implementing the circuit breaker pattern a circuit breaker prevents service from performing an operation that's likely to fail here's how it works once again we are in a situation where our dependent service is already in a bad state unable to provide successful replies our client then makes a request to our service however this time instead of invoking the failing dependency directly there is an intermediary that we will call the circuit breaker the circuit breaker will now start monitoring the results of each of the requests that go through it that go through it to the external dependency and when it detects that the rate of failure goes beyond the configured threshold it will immediately stop letting any more requests go out and will fail them right away this is what we call opening the circuit after this request will just keep failing immediately during the configured wait time which would hopefully give the dependent service enough time to go back to a healthy state eventually the circuit breaker will let some requests go out to verify if they succeed and if that is the case it will close the circuit again letting all 40 requests reach the dependent surface that's how the circuit breaker prevents our service from reaching resource exhaustion while at the same time avoids overwhelming dependent services until they get a chance to recover let's go ahead and implement the circuit breaker pattern in an inventory microservice to implement the circuit breaker pattern all that we have to do is add a new transient http record policy just like we did for the weight and retry policy so here we are again in the inventory microservice in the startup class configure services method and i'm going to scroll down a little bit here and remember we have already added policy for weight and retries and we have a policy for timeouts so what i'll do now is i'll open yet another section here to add our our next http record policy so i'll do a transient http load policy remember we want to do this just before the timeout and not after so that this policy can also wrap the benefits of the timeout policy so open parenthesis here and what i'll do is i'll just copy this little section here so that we are we are properly combining this policy with the time with deceptions that could come out of the timeout policy but then what i'll do is i'll invoke the circuit breaker async method here and i'll open parentheses and here we have to suffice the parameters for circuit breaker so the first parameter that we have to define here is how many tries we're going to allow or how many requests we're going to allow through the circuit breaker before the circuit has to open right so in our case let's say that's going to be three so three failed requests are going to are going to go through the circuit breaker before the secret breaker actually notices that yeah there's a problem and we have to open the circuit next comes the duration of the or time span of the other break so this is how much time we will keep the circuit open so let's say this is going to be time span from seconds let's say 15. and that's really most of what you have to do you don't have to do more than that to enable the secret breaker uh but just like we did with our tries let's add a couple of functions here to get an insight of what's going on behind the scenes so what i'll do is i'll say on break so this is a functional that will be used when when the secret opens so i'll say outcome and time span okay so in this case we want to add a log message and stating that the secret the secret breaker is opening so this is going to be really very similar to what we did for uh for our weight and we try so i'm actually going to copy these three lines from here i'll copy them over here for our own break function and i'll just change the message the following way so i'll delete this and i'll say opening the circuit for and this is going to be time span that total seconds seconds okay so that's what's going to happen when the secret breaker opens and then next we're going to add another one for the on reset on reset function that's not going to receive any parameters and in this one we're going to do something very similar so i'll copy again that that line those lines paste them there and in this case we're just going to say closing the circuit okay so that's really all you have to do to enable secret breaker so again we are waiting we will allow three requests to go into secret breaker and if those three are failing the rate the circuit is going to open then it's going to wait 15 seconds uh before allowing any new request to actually totally try to to reach the other end uh during those 15 seconds things are going to just fail right away and then we have functions to lock what's happening when the secret opens and when the circuit closes and now i'll go ahead and i'll open my terminal so i will save this file i'll open the two terminals using the like in previous lessons i have two terminals inventory service on left side catalog service on the right side i'll do.net to run in both sides okay notice we keep getting these warnings about the build service provider issue that we talked before but like i said that's this is just for demonstration purposes so now i'll get back into postman and we'll try out that inventory api to get all the items in the user's inventory see what happens so i'll just go ahead and hit send and notice the left side that we tried we failed so we waited for 2.02 seconds then we tried failed waited for 4.64 seconds and then at that point the circuit actually opens for 15 seconds so we're waiting at 71 seconds for the next try but the moment that we try this again things fail right away as you can see on the left side and you see if we see what's happening in postman yeah we're getting that error the circuit is now open is not allowing any further calls and if we try once again uh it may take one or two seconds but it will fail because the sequence is open and if we just keep trying and keep trying uh we're getting an immediate result so this is the effect of having the circuit open so any new requests are coming here from any client or service are going to fail right away however eventually the circuit lets us go through one word request and if it notices that it's successful it opens the circuit like it happened right here we go back to postman we can see that it allowed one more request just to see if things are healthy once again and it got a 200 result and then it said yeah closing the circuit and it allowed things to keep working once again so that's how the secret work breaker works and that's how it can help us prevent overwhelming other services or having to waste resources and cause resource exhaustion in our microservice at this point we are doing a fairly good job at handling parts of failures between our inventory and catalog services however could there be a better way to have inventory get all the information he needs from catalog without having to rely on catalog to be available most of the time in the next module we will learn about the asynchronous communication style and how it can help us enable a much more resilient communication between our services in this model you will learn about the asynchronous inter-service communication style the challenges it can help solve how to implement it via habit and queue and mass transit and how to enable eventual data consistency between our two microservices by the end of this model you will have a solid understanding of the following the basics of and when to use asynchronous communication between microservices how to enable microservices autonomy and the impact to the sla how to use a message broker for asynchronous data propagation how to stand up a ravine queue message broker via docker compose how to publish messages to ravit mq via the mass transit framework how to consume messages from gravitmq using mass transit and how to implement eventual consistency of data propagated across microservices in this lesson we will learn about the asynchronous communication style and how it can help us enable much more resilient communication between our services imagine a scenario where after receiving a request from a client our microservice needs to reach out to two other microservices also each of these services need to get in touch with other services which in turn might need to further reach to more services there may also be services that depend on the services that our service depends on we originally fine tune our service so that it never takes more than 300 milliseconds to respond to our client requests however when we started making synchronous calls to one of our dependent microservices we had to add to our time the 200 milliseconds that that service can take to respond that was still okay in the beginning but unfortunately when that dependency eventually started calling another dependency and that one yet to another one our oral average latency bumped to 1450 milliseconds which is bad on top of that if one of our deeper indirect dependencies starts failing even if temporarily it can cause all of the services that depend on it to also start failing and the effect keeps cascading until potentially most of our system becomes unavailable one important concept that you should keep in mind as you embrace microservices is the service level agreement or sla the sla is basically a commitment between you as a service provider and the client for instance as part of our sla we could have defined that our service can be expected to be up and running 99.9 of the time so when our clients choose to use our service they should expect it to be down approximately 44 minutes during the month which the owners of the client will have to decide if it's susceptible however when using synchronous communication calculating such numbers for our service sla gets more complicated our deepest dependency is also advertising at 99.9 uptime in their sla and let's say that all of the services initially advertised at the same value however in our scenario when dependency 4 fails it impacts the sla of dependency 3 which now sets its sla down to 99.8 this in turn impacts the sla of dependency 1 and ultimately impacts our own sla now with an sla of 99 at six percent of time our clients would be subject to about 175 minutes of downtime across demand which is way below of what we wanted to provide initially so the synchronous communication style suffers from an increase of latency due to the chain of calls it can significantly amplify the impact of partial failures and can potentially reduce the sla of our service now let's look at the asynchronous communication style here the client does not have to wait for a response in a timely manner and in fact depending on how the communication has been set up there might not be any response at all to enable such communication there is usually an intermediary called the message broker which is pretty dumb in nature meaning that it has no business logic on it and it is also highly available with the message broken in place the service client sends messages to the broker and the broker forwards the messages to receivers as soon as possible the messages can be received by two types of receivers a single receiver in which case we think of the message as a command via which the client requests an action on the receiving service for instance when a purchase operation starts our trading service will send a command to our inventory service asking it to grant items to the user's inventory and another command to an identity service asking it to david kill from the user we could also have multiple receivers where there are multiple services that subscribe to the events published by the client service this would be the case if for instance our catalog service would like to publish any updates with catalog of items so that other services can be informed about the changes one of the key benefits of using asynchronous communication is that it enforces a microservices autonomy let's see how it's enabled in a single receiver scenario we would have again our client talking to our service but our service will not talk to its dependent service it will instead send an asynchronous message to a broker and he will immediately acknowledge to decline the successful reception of the request the dependent service will consume this message from the message broker as soon as possible and will eventually provide a reply via the same broker at that point the client can request a status of its initial request to our service or our service can notify the client of the response all of the services in our system would follow the same message-based approach including cases where a reply is not required from the call service the great thing about this kind of layout is that when one of the dependent services fell it would not cause any impact on the other services since all of them have been decoupled from each other and only talked to the message broker so the same sla that one of the services presents can be honored across the entire system assuming that the message broker offers high availability so with asynchronous communication partial failures are no longer propagated each service has its own independent sla and best of all the autonomy of all microservices is enforced given the lack of coupling between them one of the nice things that asynchronous communication provides is the ability to asynchronously propagate data across services in the synchronous communication scenario when the client requests the user the user's inventory and since the inventory service only has the data that's relevant to it inventory has to first talk to the catalog service in order to retrieve additional details about each item how comes asynchronous communication health here well thanks to the presence of the message broker what we can do now is have the catalog service publish an event each time a catalog item is created or updated or deleted such event doesn't have to have all the details of each item but only the ones of interest to client services we can then have our inventory service listen to these events and create its own collection of catalog items in its own database as long as we have a highly available message broker the list of catalog items in the inventory database should be eventually consistent with regards to what's in the catalog service now when the client requests the user's inventory inventory has no need to go out into any dependent service to request item details it has everything it needs in its own database and it can immediately provide a reply to the client with no additional latency so thanks to asynchronous communication we can enable eventual consistency across our system the autonomy of our services is preserved and the previous inter-service latency is reduced or completely removed in the next lesson we will start implementing asynchronous communication between our two microservices we will introduce revit nq as our message broker of choice given that it supports the amqp protocol it is lightweight easy to run locally and is very popular in the open source community revit queue introduces a concept of exchanges which you can compare to a mailbox when a service like catalog needs to publish a message it will send it to an exchange in gravity mq and with the appropriate bindings in place the exchange will distribute the message to any of the configured queues from there habit and queue will take care of delivering the message to any subscribe services like inventory we could use revit queue directly in our code but we would first need to create the exchanges and queues and configure the bindings to ensure messages are properly routed also our code will be tied to ravitmq and if we ever wanted to move to another message broker we would need to rewrite a good part of our services code for this and a few other reasons we will instead use mass transit on top of raviten queue mass transit is a popular open source distributed application framework for net mass transit can take care of doing most of the heritage mq configuration for us and is able to integrate with multiple other message brokers while allowing our services to stick with a higher layer of broker agnostic apis as part of this mass transit introduces the concept of a publisher and a consumer which is what our service code will focus on let's start coding just like we need to define dtos to establish contracts between a rest api and our api consumers we also need to define the contracts that define the messages to exchange between services that use asynchronous communication however this time we will define the contracts in a separate project mainly because we will later package and share the contracts with other services so they can easily use them so let's start by defining the contracts that our catalog service will use to send events asynchronously anytime an item is created updated or deleted so here we are once again in our catalog microservice project and what i'll do is i'll open my terminal via ctrl j and then i'll switch to the search directory and i'll go ahead and create a new class library so i'll do dot net new classlip and the name we're going to give it is play that catalog that contracts okay so now we have a new contract project over here and before we forget let's make sure we get a reference from the catalog project into the contract project so what i'll do is i'll go into play that catalog that service and then i'll do dot net add reference and it's going to go into play that catalog that contracts lay that catalog.contract.cspro so i'll make sure that we can use this contract from the a catalog service now let's go to our let's collapse this and let's go to our contracts project and let's actually collapse this terminal and let's delete this class one we're not going to need it and let's actually bring in a brand new file into the contracts project we will call it just contracts.cs let's give it a namespace i'm going to replay that catalog that contracts and here we're going to declare three records that are going to represent these contracts four items are getting created updated and deleted so let's start with the created case so public record catalog item created so here we need to specify not everything about the catalog item but really the stuff that our consumers are interested in so in this case what our consumer needs in this case inventory needs to know is the item id the name and the description so let's specify that so good item id let's import the missing namespace the name and the description and then we need to specify the the event for when items are getting updated so i'll just copy the one for created since these are very similar uh i'll say update okay it's really the same information we're going to emit any time and writing has been updated and then lastly let's define catalog item deleted and in this case the only thing that we need to communicate is the id of the item so in this case it's just going to be good item id so with that we have defined all the controls that we need and in the next lesson we will update the catalog service to start using these contracts and a few new nuget packages to start publishing messages to a service broker it's time to update our catalog microservice so that it starts publishing messages anytime an item is created updated or delete it so i'll start by opening a terminal so that we can bring in a couple of uh nuget packages that we're going to need so here i am in the play that catalog directory i'll switch to src and to play that catalog that service not the contract but the service one and here i'll add the net add package masstransit.asp.net core okay so this one brings in a bunch of functions that we're going to use in order to interact with the mass transit libraries and the next package is going to be mass transit that habit mq so this one introduces a couple of additional api so that we can explicitly use the a rabid nq service bus okay so with those added let me close this terminal and i'll go to play catalog service and into our items controller and perhaps i'll close the navigation pane for now and here we're going to do a few things first let's get rid of this temporal code that we added in previous lessons to simulate temporal failures so we don't need really any any of these anymore remove that remove that and also remove this request counter that we had added now the first thing that we're going to need here in order to be able to publish messages is what we call a polish endpoint so this is the this is the class that allows us to really communicate that we want to send messages to some location so i'm going to declare a variable of type i publish endpoint let's call it just publish endpoint and for this we're going to need to import the mass transit namespace and then we're going to receive this variable as via dependence injection into the constructor and then we will grab that instance into our pollution point variable now we can go to each of our controller actions operations where we want to push a message and start sending those messages so i'm scrolling down into our post async method and what we're going to do is that just after creating the item in our database we're going to publish a message announcing that the message has been that the item has been created so i'll do await foolish endpoint dot publish and here we're going to use our new set of contracts and we will start with our catalog item created contract and let's see control dot we need to import the play catalog contract namespace and here we have to provide of course the item.id item.name and item.description and that's really all you have to do to publish a message and i'll copy this line because now it's time to go to our put async method and do something very similar so just after updating the item into the database over here let's add and paste that line but in this case the method is going to be catalog item updated and we will choose the existing item variable that we have here we'll use the the id the name and the description i'll copy this once again and let's go to our delete async method and again just after removing the item we will go ahead and publish a message saying that we have a catalog catalog item deleted which is going to be just the id that we received from the from the parameter so yeah so that's all you have to do and so now any any consumer of these messages that is listening to to to the queue to the right queue it will be notified that an item has been created updated or deleted now what we have to do is to do the proper registration in startup uh to configure and to register the classes that we need for mass transit from wmq so i'll open my explorer here and i'll go first to upsetting.json here just like we did with mongodb we need to add a little section for our rabbit enqueue settings so i'll open a section here let's name it rabbit mq settings open a section here and here the only thing that we're going to declare at this point is the host so which which where is this uh this gravity mq server living and in our case since this old local machine is just going to be localhost you could specify more details like username password and a bunch of other settings but for now for local purposes we will just accept the defaults and we will go with localhost save that now just like we did with the other settings libraries settings classes we need to introduce a class that represents a habit and q settings so that we can use that in startup so i'll create a new settings directory here now and of course we will move this later into our shared command command library but for now let's just do it here and we will do that refactoring later on i'll add a new file into the settings directory let's call it rabbit nq settings that's cs let's add a namespace that catalog let's service that settings and then let's declare our class public class habit mq settings and as we know the only thing that we need here is the host so i'll declare our string host and as with any other settings class we will do use this as as init as opposed to set because and nobody should be setting these these properties after they have been uh deserialized from the configuration file i'll save that and now it's time to go to startup to register with the services that we're going to need so i'll go to startup and again i'll collapse this navigation pane so here in startup i'll locate our configure services method right here and then we will add the mass transit a classes just before the controllers let's do it here we're going to say services that add mass transit and we will receive a variable here that we're going to be using to configure things i'll open a section here close this let's see if we're missing something yeah so we need to import the mass transient space and then we will use this x variable here which is that we call the configurator uh to specify the type of transport that we want to use in our case that transfer is going to be rabbit and q so we have to say x dot using rapid mq and then we need to receive we need to specify a function to configure the habit and queue so in this function we're going to declare two parameters which is going to be the context and the configurator and then let's give it a let's give this function a body stat say and the first thing we're going to do here is to get an instance of those rabbit mq settings so that we can figure out what's the host that we're going to use so we will just say have it mq settings it's going to be configuration get section and then the section that it should have the name of covet mq settings have it into settings class and let's see if we're missing something yeah we need to import the play catalog service settings namespace and when we have that we can say okay so now get it as a habit enqueue settings type okay so we have the settings and now what we can do is use the configurator to set the host where our gravity mq instance lives and that's going to be in gravitysettings.host and now we'll add one more line this is not necessary but i think it's very handy and this line is going to help us define or modify a little bit how the cues are created in the rabbit and queue so i'll do configurator dot configure endpoints and here we're going to receive the context and afford mater and what we're going to use is the kebab case endpoint name formatter see if we're missing something yeah we need mass transit that definition and in this formatter we're going to define um we're going to define first uh the prefix that we're going to be using for our cues and that's going to be service settings dot service name and then we will not need to include the full name space of our classes in those queues so we'll say we'll just say false here and lastly we'll add one more line just after this one to start they must transit the hosted service so we will say services that add holds service and this is the service that actually starts the rapid mq bus so that messages can be published to the different exchanges and queues in rapid queue i'll save that and for one last change i'll go to our i'll go to our explorer and i'll go to app settings at development.json and this is something that i like to do more for demonstration purposes than for anything else but this is a changing the default login level from information to debug so i found that this is going to be very handy for us to understand what's going on behind the scenes when messages start flowing between services so we'll do that over here and at this point the catalomic service is ready to publish messages to have it and queue but we don't have a rabbitmq instance available just yet in the next lesson we will expand our docker compose file to also stand up a rabbitmq docker container that our catalog service can communicate with it's time to stand up our rapidmq message broker and of course we'll use docker for that so here i am in visual studio code and what i'll do is i'll open our play.inf directory play that infra and then i'll do code.r and here i'll just go ahead and close this close that and i'll open our docker compose java file and perhaps i'll collapse this so the first thing that i'll do is i'll go ahead and remove this comment that we had at the top and now we can go ahead and start declaring our gravity mq service so just like we did with we'll come here and we will declare a service for driving queue let's name it having queue and then as usual the first thing that we want to declare here is the image that we're going to use that image is going in this case is going to be the standard rabbitmq image that includes also a portal to manage a derivative infrastructure so that would be driving queue management then we will mention the container name the name that we're going to give to this container and it's just going to be rabbitmq then we'll go for the ports section we're going to open uh two ports one port for our services to communicate without having queue and then another port for us to be able to navigate to the cabinet and queue portal so the first port is going to be five six seven two maps to the same one internally and the other port is going to be fifteen six seven two which maps to the same port internally too so the first one is going to be used by the services to publish messages to or to consume messages from hybrid and queue and the second one is going to be used to be able to go to the portal to the writing q portal then we're going to go to the volume section and we're going to declare a volume also for having queue which is important because we don't want to be missing those messages if the gravity and queue container goes down so i'll just declare gravity mq data and now we have to uh we have to map that volume into some location in our rabbit mq image or container so i'll declare volumes i will copy have it in queue data and then location the location that you want to map inside rabbit enqueue is going to be var leave grab it mq and one more thing that we have to suffice here which is pretty important is the hostname so hostname and we will give it the value of rabbit enqueue so this one here is pretty important because this is associated to how having mq stores data internally and if you don't specify it then it gets a random value and then each time we restart the container gravity and q would store data in a different place which is not going to help us really a lot so keep in mind you always want to specify here it doesn't matter what value is here but you have to specify some value okay so with that done i'll do ctrl s to save this file and then i'll open the terminal and it's time to start this container via docker compose up dash d hit enter and this is the first time that i'm pulling in the hovering q image so you have to download it to my machine like i said next time it will be faster so yeah now we have we have raving queue up and running over here and with that we can start trying this out so i'll go back to our catalog project and here we're going to start the catalog the catalog web server uh but we'll do it via dotnet run so that we can take a closer look at what's happening behind the scenes so i have opened the terminal ctrl j then i'll do src and then i'll do data catalog that service and then let's just do dot net run here i'm going to collapse this also and so a couple of things to notice here is that uh so yeah mass transit is doing its job it's starting the starting the bus and then it has connected to it has connected to gravity and q in port 5672 is using the protocol aem qp so here's where you can see the actual address of rabbit enqueue in the docker container uh like i said this is the one port to connect uh today to the queues and so things are looking ready on this side so now we'll go to postman and what i'll do is i'll go ahead and i will create an item in our catalog so i'll go to our catalog api and i'll open the post one and here i'll create some new item let's say this time we're going to create an antidote so antidote curse poison and then price going to b7 and i'll hit send so that then got created in the database but now let's see what else happened so if we see now here yeah the item got created but also an exchange was created uh in gravity and queue so mass transit created this exchanging gravity queue for us that's one of the nice things about mass transit so we don't have to create it manually and it got the name play catalog contracts and then the name would be catholic item create so an exchange will be created for each of the messages that we publish from from catalog and you can see that after created exchange it also sent the message to that to that exchange the message was sent over there and so if you want to see how this looks like in gravity and queue actually we can go ahead and check out the java and q portal so let's open that portal now here we are in the browser let's go to localhost 15672 is the easy place and here we're going to use just the default username and password for having queue so that's going to be guest and it's exactly the same password just guest login and in this ui you can see a couple of a bunch of things but really the one thing that i wanted to show you now is the uh the exchanges and as you can see there is a exchange created here cattle guiding created and issued i find out meaning that anybody listening to this exchange will be able to get the messages and then cattle guide and create it i'll go in there and then there's not much to see here because the exchange just takes messages from one place to the other it's not going to store the messages and then as you can see the exchange right here in binding section it is not connected to any it doesn't have any bindings just yet and that's because we don't have a consumer of these messages yet which is going to be inventory and but it's not there yet so the queue has not been created and so there's no destination for these messages just yet and so at this point we are able to publish messages from our catalog service anytime our items database is updated so in the next lesson we will generalize some of the code that we have added here into our common library in preparation for having inventory start consuming the polished messages let's move the code that configures mass transit and rabbitmq into our common library so that things get easier and cleaner for catalog and any future mic services so here i am back in our catalog project and i'll start by going to our settings folder and i will copy our raven queue settings file copy that and then i'll switch to our common project our common library i'll open our settings folder and i'll paste the copied class and i'll grab the name space from some other of our settings classes i'll just fix that namespace here save and now before adding the mass transit classes let's bring in the nougat packages that we're going to need over here so i'll do ctrl j let's go into sirs play that common and let's add the same packages that we already added into catalog so dot net add package mass transit that is b net core and then let's do mass transit that have it mq all right so with that done let's go ahead and create a new folder let's call it mass transit and perhaps let's close this terminal for now and just like we did with mongodb let's add an extensions file here but we're going to add our handy extension method so let's first declare namespace click that command that means transit and now let's create our class it should be a static class and now we'll bring in our extension method so this is going to be public static iservice collection add mass transit with rabbit mq so that way we can do all the registration for mass transit and everything queue in one location let's add the missing space and let's expand let's extend i service collection services and here is where we're going to bring that code from the catalog service i'm going back to catalog into the startup class scrolling down i'll copy these lines copy that into common and i'll paste them over here and now let's start fixing all these missing name spaces so admins transit we need to import using mass transit and then uh for gravity mq settings we'll need to import play that command.settings give that case endpoint name for matter we'll need my strategy.definition okay and just before we also will need an actual instance of the configuration class and an instance of our service settings class now these are very similar to what we did in mongodb so let's see if we can get something from there so mongodb extensions let's see let's yeah let's grab these two lines let's close this and into this spot there and let me collapse this navigation pane now so here we also need an entry an import for eye configuration let's grab that extensions configuration and you can notice that there's no service provider variable available here however we do have a service provider and that is this context class that that's that's over here this ibus registration context exactly a service provider so we'll use that as the class that can give us an instance of i configuration we can also fix this other configuration member here and let's also rename this x variable here to something more meaningful let's name it configure and since we are here one more thing that we can do is to perform the consumer's registration the consumers are the classes that are in charge of consuming messages from the rabbit and queue message queues we have not created these classes just yet for catalog because catalog is not consuming but just publishing messages but we will create these classes inventory so since inventory will be using this method we might as well just add that registration over here so i'll open a couple of lines here and what i'll do is i'll just say configure dot add consumers and there's a few ways to register consumers and the way we're going to do it is that we're going to specify the assembly that should have all the consumers already defined and that's going to be the uh the entry assembly for whichever microservice is invoking this this class so to get that we're going to say assembly and we need another import here using system reflection that get entry assembly and that that should do it okay so any consumer classes that are in that assembly will be registered by this method and finally let's go ahead and return our services instance to complete this method okay so with that let's make sure everything is built in so i'll do ctrl shift b and yeah everything builds just fine and now let's go ahead and package it all these new changes into a new version of our nougat package so let's go back into our powershell terminal and perhaps our clean this and listen we did before we're going to do dot net pack but this time we're going to specify a version last time we didn't do it and that generated version 100 for package this time we need to increase the version so that our consumers can actually notice that there's something new available in the in the package so to specify version what you can do is use the d p sorry parameter and then you specify package version and then you specify the version so i'll say 1 0 1 and then just before we'll specify an output directory it's going to be the same location as before packages enter and we got a new nuget package created right there so now let's go back to our catalog project and start taking advantage of this package and first thing i'll do is i'll delete our settings directly once again we don't need it get rid of it then i'll go to our project file and since we're bringing in this nuget package that has all the master assets stuff we should not need these two references so i'm going to get rid of them save and now what i'll do is i'll just go to our play.com dependency and i'm going to bump the version number here this is one zero zero bumping it to one zero one i'll hit save this pop-up dialog shows up asking us to resolve the updated dependencies so i'll do a click on restore and that's going to bring in the updated package into catalog so i'll close this and i'll close that and now it's time to update our startup class to take advantage of the new package and first let's get rid of this unneeded import at the top and now what we can do is just since it's fluent let's expand on top of our admonk repository so let's just do add mass transit with rabbit enqueue we may be missing a namespace we need to import play.com on that mass transit and then that becomes a one line that we have to run to execute all this stuff that we were doing before so i'll get rid of all these lines save and that should be good enough i'll do a ctrl shift v to make sure that things are compiling yep it's looking good so let's go back let's open a new terminal here and let's verify that things keep working properly so i'll do i'll go to src it's not into contracts we want to go into service and then i'll do dot net run yup so yeah we are connected we have connected to the rabbit and queue so it's time to do something about messaging so let's go back to postman and last time we had created this antidote item and so instead of creating a new one why not let's try the an update operation so i put so i'm going to just copy this and then let's go into put and then in the body we're going to just paste paste this so it's the same antidote curse poison but let's say that the price is now 9 and then let's bring the id hopefully the same id that we used before so copy this id into the url for the put operation and then i'll hit send so we go 204 so it was a success and now let's go back to vs code and yeah just like before the exchange was declared and the message was sent to the exchange as you can see but this time we should have a new exchange so let's go back to riveting queue briefly and here let's go now to exchanges and as you can see there's a new exchange here cattle guiding updated so things are working properly and one last thing that we have to do here is to actually publish the catalog contracts as a nugget package so that inventory can use it in the next lesson so let's go ahead and go back to catalog and here i am i'm going to do ctrl c in my terminal so that the whole stops and then i'll switch to our play dead catalog that contrast directory and here i'll do what we did before so dot net back and then output directory packages that should go ahead and produce our contracts package hit enter and there it is so now we have a contacts package that inventory service will be able to use to consume the messages in the next lesson we will update our inventory service so that it can consume the messages published by catalog the whole point of moving inventory to using asynchronous communication is to have its own database of catalog items that it can use without ever having to get in touch with the catalog service api therefore let's start by defining the entity that represents catalog items in the inventory microservice so here i am back in our inflatable inventory microservice and i'll open our entities directory now this new entity that we're going to create has some similarities with inventory items so i'm actually going to start by getting a copy of inventory item so i'll just copy this and i'll paste it right there and let's rename this into catalog item catalog item and we rename this as catalog item which also implements identity but in this case it's not going to have most of these properties but it's only going to reduce the id now remember the categorizing has a bunch of properties in the catalog service but here we will only introduce the properties that make sense for inventory so in this case this is going to be we'll start with the with the name and then we will also need description okay so keep in mind that as you are bringing in these entities from other microservices you don't have to have everything that these entities have in the other service it's only a the version that the new market service needs in this case us id name and description with that done let's go ahead and start bringing in the nuget packages that we need for this so i'll go to play.inventory.service.csprock and then i'll open my terminal so let's go to src enter the service play inventory service and let's get a reference to our new a catalog contracts nuget package so dotnet add package play that catalog that contracts remember this has all the contracts that we can use to consume messages from catalog okay with that done let me close this and now you can see that we have applicator contracts here but we also need to bump the version of play.com because remember we added some new uh so some new classes in there so album from version one zero zero to version one zero one i'll save that let's go ahead and restore the new the new nugget package now we can close this close this these files now it is time to define the consumers and like i said before the consumers are the classes in charge of consuming the messages that have been published by any other microservice so to define the consumers let's go ahead and create a new folder let's call it consumers and we have to create one consumer for each of the different operations that happen in catalog so that's for creation update and delete of of catalog items so i'll go ahead and create a new file let's name this one catalog item created consumer copy the name let's give it a name space service consumers okay so this is our catalog item created consumer and the first thing that you have to do about this consumer's class is to make sure that they are actually consumers and to do that you have to implement the iconsumer high consumer interface which is part of mass transit and i'll do control dot so using mass transit and here you also have to specify what is the type of message that this consumer is going to handle and that type of message is actually coming from them the contracts that we're bringing in from catalog so in this in this case it's going to be catalog item created let's see if we're missing something using play.contracts so then let's go ahead and implement this interface so i'll do ctrl dot here implement interface and as you can see we just have to implement one method that which is the consume method so which is where we're going to actually uh perform the action of of consuming the message and so what we want to do when we consume the message is actually a storage in our local catalog items database so to do that let's first introduce a repository that we can use for for that so i'll declare read-only i repository of type catalog item okay so this is the new entity we just introduced it for catalog guidance in inventory all right see if you're missing something play that common for i repository and play that inventory service entities and now we need to inject this repository in the constructor of this class so let's define a constructor so public catalog item created consumer and so here's where the repository comes in okay so let's say this data repository equal repository let's now go ahead and implement the consume method for this class so i'll get rid of this and let's first get a copy of the of the message so the message that we're receiving is available in the context variable as the message property so let's grab that copy there and then what we want to do as we consume this message is probably first make sure that we have not consumed this already right uh we we may have a very consuming message of the creation of an item uh with the idea that we're going to get in this message uh and if we did we already would have that into the database so let's make sure that we don't have it and if we do have it let's just return there's nothing else to do but if we don't have it we'll go ahead and create it so let's see item is a weight repository not get async and that's going to be in message dot item id let's also make sure that this method is async and then if item is not new then we will go ahead and return okay because in this case it happens to be that we already created this item in our local database so why would we create it again if not we will say new catalog item and then we'll say all these message.item id name is message that name and description is message the description finally we'll go ahead and do repository dot create async of this item okay so that's all you have to do to consume a message that represents a new item that has been created in the catalog like i said we just verified if the item is already here because it could happen in the cases where for some reason the publisher publishes the same message twice and so we don't want to be having errors here because we already have the item in our catalog guidance database so if we don't have it we'll go ahead and define it and create it into our local database let's go ahead and do something similar for our a update so when a catalog item has been updated so i'll get a copy of our of the consumer and let's just rename it into catalog item updated consumer okay so i'll do this and then the the message is catalog item updated so let's fix a couple of things constructor there okay so we are consuming now catalog item updated and here the logic is going to be a little bit different so for an update it could be that we already have this inventory item in our local database so in which case we'll need to go ahead and just update the properties or it could be that this is the first time that we receive this message for this item in which case we'll go ahead and create it so now in the case that uh so first just before we can go ahead and get the item but if the item is new so we'll change this if item equals no then we will go ahead and define these lines that we had over here there so editing is new we don't have it in the database so let's go ahead and create it otherwise let's just update the the properties that make sense in this case it's going to be item.name equals message.name and item.description equals message.description and in this case let's go ahead and call weight repository that update async item okay so quick recap we for an update operation we go ahead find the item if we cannot find it we will go ahead and create it into the database and if we find it we update nameless description and update it into the database now let's go ahead and implement our third consumer which is going to be four deleted items so again i'll get a copy of this last consumer paste here and then rename it into catalog item deleted consumer copy this name so i'll update the name of the class the constructor and then let's make sure we also update the message that we're handling here this is catalog item deleted here and there and in this case things are even easier and so we will go ahead we'll try to find the item and if we cannot find it uh it means that for some reason it does not exist in our local database so there's really not much more to do in our case so we will go ahead and just return we don't have it just go ahead and return and if we have the item then we can go ahead and say weight repository remove async message.item id okay so with that we have our three consumers defined and now it's time to perform the proper registration in startup and before we can do that let me go to app settings.json and we need to declare those rabbitmq settings so that we know how to communicate to have it in queue so i'll actually go back to catalog our catalog service over here and i'll just grab those three lines for hybrid mq settings for an upsizing adjacent and then back to inventory we will add that over here same thing we're talking to localhost for arriving in queue now let's go to startup okay um perhaps i'll collapse this for a moment so let's do a few things here so as you see we still have this logic to use the catalog client to talk to the catalog service uh we will not be using this anymore but let's keep this logic around in case you want to reference it later but what we're going to do is we're just going to refactor it into another method so we don't have to have all this stuff hanging around here so i just selected all this logic to use the you know the retries and the configuration of the client i'll do ctrl dot and i'll say extract method so we'll name this method at catalog client and i'll take this method and just send it to the end of the file so that we don't have to see it frequently and now a couple of things that we have to do here for for uh our new a catalog items repository and mass transit so first we need to introduce a new repository here for the catalog items so i'll say add repository catalog of catalog item and then we need to give a new name for this new collection of items in this case it's going to be catalog items okay so keep in mind that both of these are going to live in the same database the same inventory database but it's two collections one collection for inventory items and one collection for catalog items and then we also need to add the mass transit registration so i'll say add as transit with habit mq let's add a missing space and that's pretty much it on startup then let's go back to our explorer one more thing that i'll do is just like we did in catalog let's flip the default log level so that we can see also what's going on regarding all these message exchanges so i'll change this to debug and with that our inventory service is ready to start consuming messages but one more thing that i'd like to do is to actually clean up our databases and i like to do this because at this point we we do have some data both in inventory and catalog site but that that data has never been synchronized at all so it will be better to use a start clean in a situation where both sides are actually synchronized from the start so i'll go back to mongodb the mongodb extension i'll expand this and as you can see we do have the catalog and inventory databases so to clean them up i'll just right click and say drop database i'll drop catalog and then i'll drop inventory you may choose to not delete them but that could cause issues as as you start moving forward so it's better to use starkling in this case at this point i'll start our micro services so i'll do ctrl j to open the terminal i'll go to my terminal and perhaps i'll do clean and just so that we can see things better what i'll do is i'll see i'll collapse this and i'll bring in yet another terminal with the split terminal put on here so that we can see services in both sides so perhaps what i'll do is i'll switch to a catalog on the left side so i'll go to play that catalog and then play catalog service and on the right side i'll stay in inventory so i'll do play inventory service okay so let's clean both sides and now we can start both services i'll do dotnet run both sides and now notice in the right side that a few new things are happening and perhaps i'll move this around a little bit and yeah it may be a bit hard to see but exchanges has been declared for the for the consumers that we declare here you can see we have exchanges for a cutter guiding created updated and deleted and if we scroll down a little bit let's see these exchanges are now connected to the queues so you can see that this this exchange is now connected to our new inventory catalog item updated queue same for created and deleted and the consumers are reporting that they are okay so they're ready to start consuming messages okay so let's move this over here so now let's see this in action so let's go to postman and what i'll do is i'll start by creating a brand new item so i'll go to our post item api in play catalog service body and let's define our classic potion example again we'll say potion sources small amount of hp and the price is going to be 5. i'll go ahead and hit send the item has been created and then let's go back to our terminals and see what happened so as you can see on the left side the change was declared cut the guiding created and the message was sent right so cattle guiding created was sent and then the right side we can see that now we actually received the message and that was handled by the cattle guide and created consumer so if things went uh correctly we should now have a copy of the catalog item in our local a catalog guidance collection in inventory site inventory database let's go to mongodb let's see what we have so i'll expand this so we have the catalog database with this item created here and then we'll expand inventory and then you can see that we do have now our catalog items collection with that item created over here so the item has been replicated from catalog into inventory we can now take a look also the activity that happened in driving queue so let me go to the driving queue portal over here and let's take a look at exchanges so see that we now have the three exchanges uh for category created deleted and updated from the catalog side and then also the the changes from the inventory side created outdated and then if we go to queues you can see that now we have the three queues for the three types of events and if you go to cattle guide and create it we could see here any activity that goes across this queue now the item has been already consumed so there's nothing not much to see here but let's see what happens in a case where let's say that our catalog service is is not running right so actually our inventory service is not running so our catalog service pulls some message but inventory is not running now that the queue is up and running things are going to work in a speed of a different way so let's go back to inventory and i'm going to stop the terminal on the right side i'm just going to do ctrl c inventory stops now and let's go back to postman and create yet another item so i'll create an antidote which cures poison and price is going to be seven so i'll go ahead and pause this and then if we go back to rabbit and q let's see gather guy and create it you can see that now there is a one item in the queue as reflected by this as you can see it's one item which is waiting to be consumed by somebody so here is where the nice thing about asynchronous communication starts happening so there's no need for cataract to be up and running all the time uh inventory can nicely just keep polishing these updates uh to their to to their items and then whenever inventory comes back it should be able to consume the the message and in fact let's go back to our terminals over here you can see that the category was created on the left side and now let's go ahead and start a terminal on the right side let me collapse this once again okay so on the right side i'm going to do.net run again and then you can see that right away inventory is able to consume the new message so the databases should be in sync again we can see that there's no more messages here waiting the message was consumed and our databases should be once again sync let me refresh this so yeah we have two documents here and we have two documents over there so things are in sync so our inventories microservice now have a nice way to stay in sync with any updates to the items managed by the catalog service in the next lesson we will update inventory so that it starts taking advantage of this new capability anytime it needs to present data that is partially coming from catalog now that our inventory microservice has its own copy of the catalog items it no longer needs to query the catalog microservice to gather additional information about the items of inventory so let's update our inventory controller to take advantage of its new catalog items collection so here we are back in our inventory project and i'll go ahead and open our controllers folder and i'll go to items controller let's collapse the navigation pane to get more space and let me scroll down a little bit and the first thing that we will do is to get rid of our catalog client because we will no longer need to invoke catalog client i mean the catalog service anymore instead of that we're going to declare another variable here is going to be just another i repository but in this case it's going to be off catalog item so this is going to be our catalog items repository and since we're introducing this new repository let's also rename the previous one so that it better resembles its purpose so this is going to be our inventory items repository let's also rename this the variables in constructor so this items repository becomes inventory as a repository and then the it's time to inject also our new catalog items repository as opposed to the catalog client here we will capture that so with that let's go down into our get async method and here's what we're going to do the first thing is that we definitely don't need to cut to call catalog client anymore so we're going to get rid of this we still need to get the list of all the inventory item entities uh represent the items in the user's inventory so this this stays but after that what we want to get is a from our local catalog items collection we want to get all the corresponding a catalog items that i mean the ones that could respond to the inventory items on inventory the today's inventory so to get that let's first get all the list of all the catalog item ids that that are involved in the inventory items collection that we have here so to do that let's do this so item ids equals inventory item entities select let's do a little projection here where item item dot catalog item id this gives us the list of all the the catalog items that we have an inventory the ids specifically and with that we can go ahead and get the actual catalog items so let's do catalog item entities is weight catalog items repository get all they sync where item and what we're going to say is that we want to get all the items that are in the item ids collection so i'm going to say item ids contains item dot id so now here we have all the catalog items that match the the items that we have an inventory for this current for the current user having that we can go ahead and update this little function here so they take advantages of this new items collection and i'll say catalog item entities is going to go here so now we can go ahead and say okay so as we go through all the inventory items first we're going to look at the catalog item entities and we're going to find the catalog item whose id matches the id of the catalog item id of the inventory that we're looking at so that's a catalog item and then we'll keep moving forward as usual and we say okay so now that we've found the inventory item and now that we have the catalog item let's go ahead and turn it into dto adding the catalog item name and the catalog item description okay so i don't think we need to make more changes to pause async so we should be ready to start using this so i'll save this i'll go back to catalog i'll just going to hit f5 to start the service and i'll go back to inventory and i'll do the same f5 to start the service and now let's go ahead and go back to postman and let's grant one item to a uh to our user so the first thing that we'll do is actually get the list of current items in our catalog to know what to grant so i'll just open our get operation in the catalog service and i'll hit send here we are we have currently a portion and an antidote so let's say we want to do the potion so i'll copy the id of the potion and now let's go to the to the inventory collection let's expand this and i'll go to our post operation where we can assign a assigned one item to a user so i go to body i'll paste the catalog item id that we just copied over here so this is the item to assign and then just like before we need a user id so and just as we did before let's use the postman function go it to generate a random user id and finally let's get some quantity let's say we're going to assign one portion to this user okay and so with that i'll go ahead and pause that sent and it's done and if it worked now our user should have one potion right so i'll go ahead and first we need to figure out what's the idea of the user that was generated and we can do that from the console so i'll click on the console and i'll go down to our post operation request body and it's right here this is a user id that was generated i'll copy that close console and then we can go to our get operation to get all the users in the sorry all the items in the user's inventory and so we'll get the items for this user i'll hit send and as you can see now we can see that this user a has a potion has one potion but more instruments interestingly it is able to show the name and the description of the potion from the local catalog items collection so it no longer needed to go ahead and and talk to the catalomic service to retrieve decision information so things are much more resilient and rely and faster now because we don't need to go out and ask for this additional info now what would happen if we go ahead and update the description of this catalog item in the catalog microservice how would that look like here let's try that out so first i'll go to back to our get items results and i'll copy a few details about the potion i'll just copy that and then i'll go to the catalog collection and i'll go to the put operation here's where we can make updates to our item so i'll just come here paste that fix indentation and let's say that instead of having this description it just says restores some hp that's going to be the new description also the id of this item is this one here so let me grab it go back to put i'll paste that here and so let's go ahead and update this item in the catalog microservice so i'll go ahead and do that and then i'll go back to our query for the inventory items of the user and let's see what happens with the description of this of this item so i'll hit send and as you can see the description is already updated and this is because as soon as we updated the item in the in catalog my service a message was published into habit mq and then our inventory service grabbed that update into its local database and is ready to present the updated description as we query for items so this is great but now what would happen if our catalog microservices is having issues actually what happens if it's completely down right so it has a major problem what would happen with it with inventory maker service can it still keep working just fine let's see i'll go back to catalog here's catalog i'm just going to stop the service so service is completely down and in fact if we go back to a postman and we try to get items again let's see what happens connection refused because the service is completely down but then let's try to get all the items on the user's inventory so i'll hit send and still works even more i can try granting yet another item to the user's inventory so just to test this out i'm going to start catalog once again hit a 5 back to postman let's go ahead and get the list of items and now i'm going to grind and grant the antidote to that same user let's do antidote into the post operation body so let's grab the antidote let's make sure we use the same user id it's right here maybe it's ready and then again like i said catalog is having problems i'll just stop it it's completely down it's not working yet i'm going to go ahead and grab that item to the user i hit send 200 okay so it looks like it was successful and then let's get all the items inventory now so i'll hit send again over here and as you can see we can query for the for all the items and all the items are showing name and description regardless of the fact that the catalog microservice is completely down so this is the power of asynchronous communication and this is how you enable very resilient communication between microservices both services are now really autonomous because they don't rely on each other to be available at any given time one more thing to consider is a case where one of our consumers is not able to consume the message properly perhaps due to some issue when trying to talk to its local database so for instance let's go to our inventory inventory service over here and i'm going to stop this for now and close terminal and i'll go here into our consumers let's say cattle guide and create consumer and what would happen if this line here is having trouble right so when we when we go into the consumer uh this this all this logic happens because we're consuming the message but if we fail if an exception is thrown in this in this case and the message is going to be sent into some error queue and if you would not be able to consume it anymore so at that point you missed an update from the from the catalog mic service so is there a good way to handle this so there's to be that yeah there's a there's a way to do that so if you go back to our to our common library so here we are back in common library and we're i'm going to go to the mass transit extension that we created before and scroll down a bit and what we can do is to enable analysis we can do is enable message retries for the consumption of the messages so you can go here and say configurator that use message message retry and then here we're going to define our retry configurator okay let's open this section and then you can say retry configurator that interval and then the first item the first parameter you're going to specify is how many times you want to retry so anytime the the consumer is not able to consume the message how many times you want to retry that consumption so let's say we want to say 3 and then you have to define the time span or our time between retries let's say that's going to be time span let's import missing space from seconds and that's going to be five five seconds let's also import another missing space we need to use using green pipes here and that's all it is so with that logic any time a message is is not able to be consumed by the consumer it will predict right three times and with a five seconds delay in there and there's a bunch of different ways to configure this depending on how you want to do your retries and with that let's just save extensions and then if you wanted to consume this in your microservices as usual you will go ahead and generate another version of the nugget package so in this case it would be it would just do dot net back it would be package version let's say in this case would be one zero two and then we send it to the same location fe4 packages package generated and then you would just go back to catalog and update its version over here to play.com102 save restore dependencies and then we would go back to inventory and do the same thing 102 save and then we'll not exercise this really in this lesson and restore but that's how you do it so from here on both microservices has this capability to retry the consumption of the messages so that marks the end of this lesson and of this model you now have two independent and resilient microservices that can collaborate asynchronously to manage a catalog of items and to grant and query for items in a user's inventory pack you also have a reusable common library that any of your mute future microservices can take advantage of and that you can keep improving according to your needs in this model you will connect the provided front-end project to your microservices to enable basic end-to-end scenarios from a modern single page application by the end of this model you will have a solid understanding of the following how to get and build the front-end project in your box how to host the front-end project in a node.js server what is the structure of the react-based front-end what is course and how to configure it in your microservices and how to debug the communication between the front-end and your microservices in this lesson you will install node.js which is a javascript runtime that will host the front-end portal and that also includes npm the package manager that provides all the dependencies required by the portal the only additional tool required to build and launch the front-end portal is node.js which you can get in the nodejs.org website let's see how to install node.js and verify the installation afterwards before installing node.js just keep in mind that the pages that you will see next will likely look a bit different depending on your operating system and the versions available at the time that you're taking this course but regardless the overall download and installation process should be mostly the same so let's now browse to the node.js website and here the first thing that you're going to see is a right away a few download buttons for your current operating system version and architecture in my case that will be for windows 10 x64 these are the two versions the one on the left is the most stable version available and the one on the right is the latest version available which may not be the most stable one but it has the latest features i would recommend going for the most stable version the lts version since that's a recommended one for most users now if the version that you would like to download is not here you can always go to the other downloads link over here and here you can pick the right version for your operating system and you also have a few other download options now in my case i'm going to go back to the first page and i'm going to download 14170 lts so just click there and i'll go ahead and start installer so click here here's installer so i'll just click next accept next next and next and at least for this course i have not seen the need to install any additional tools here so i'll just click next and install to get installation started say yes and so with that node.js is installed in the box so click finish and what we want to do now is to verify that the installation has completed properly so what i'll do is i'll just close the browser now and i'll open my visual studio code instance here and here in business to the code what i'll do is i'll open my terminal by pressing ctrl j and i'll just type a couple of commands to verify that the tools are installed properly so i'll just type node v to get the version of node.js which you can see right there 14 17 0 and and now also verify the version of npm which is the package manager that comes with node.js so i'll do mpm-v and i can see the version right there also so with this we know that node.js has been properly installed and we're ready to move on in this lesson you will explore the structure of the front-end code base how to install its dependencies and how to build and run the portal before exploring the front end code base let me give you a few details about it the front end is a simple single page application that demonstrates one way to interact with all the play economy microservices a single page application is a web application that dynamically rewrites the current web page with new data from a server instead of constantly loading new pages it is built using react which is a javascript library for building interactive user interfaces i chose react because at the time of creating the course it was one of the most popular front-end frameworks and is easy to learn assuming that you have worked with javascript before it uses create react app to simplify how you do local development how you build and debug the code in your box and how you package everything in preparation for deployment finally it is hosted in a node.js server a very popular runtime for javascript applications there are a few things that i'd like you to keep in mind as you work with the provided front-end portal in these and the next lessons this is not a course about front-end development and certainly not about react as a back-end developer myself i only know enough react to build this simple portal however i'm probably making lots of beginner mistakes and i'm probably not following client-side best practices in many places so please don't use this code as a template for the production level application but more as a basic example of one way you could interact with the microservices from a modern client you won't be coding this front end in this course there is both not enough time and i'm not qualified to teach you how to build a front end step by step instead i'm providing you the finished portal so you can use it as is it should work with no issues and no changes required provided that you make a small update to the microservices as i'll explain in the next lesson in this lesson i'll give you a quick overview of the structure of the front-end codebase with a focus on the areas that interact with your microservices as opposed to the many components that handle layout rendering and many other things finally please check out the links below if you would like to know more about the deck used in the front end project so here i am in a new bezel studio code instance and i have already opened my terminal into the projects directory where i have all my files and as you can see i have already downloaded and extracted the front-end project files into this directory play that front-end and what i'm going to do now is just switch to that directory and i'm going to open this instance of code into that directory by doing code that in dash r to reuse the window enter and here you can see the structure of the project files on the left side and what i'm going to do is first close this terminal for a moment i'd like to point you to the readme.md file so this is a file that will give you a description of what this project is about and a few other things and in fact what you can do is just open this uh preview window with this button that opens up review on the right side and close the original one so this gives you a nice view of the redmi file so as you can see this is crafty project it is creative prerequisites of the project and then it tells you how to build the project how to run it locally and also it provides a bunch of other scripts that are also available now what we're going to do is to actually follow this couple of first lines in this in this file to get started with the front end so as it says what you can do to install a all the dependencies of this a front end is a run just npm install so open my terminal once again here scroll down a bit and what you want to type just at the root of this project is npm install hit enter what this is going to do is to bring in a bunch of node models that represent all the dependencies that this this portal depends on including react bootstrap and a bunch of other things this is going to take a while depending on your internet speed because there's a lot of stuff that needs to get downloaded so just give it a moment okay so the dependencies have been installed and as you can see there's now a node models folder on the left side if you expand it you're going to find a bunch of directories have been created right so now that we have that we are ready to run the portal so to do that if you scroll down in the readme you can see that you can just do npm start and that's what i'm going to do here npm start enter so this is going to compile the entire code base and then it's going to start the node.js host okay so it compiles successfully and as you can see we get an address here to browse locally to it so i'm going to copy this address localhost 3000 and i'm going to go to my browser i'm going to paste that there and hit enter and there it is the portal is up and running in this box now in the home page here what we have is just a few basic things like the description of the project and then a couple of links uh both to go to the catalog section uh to get the list of the catalog items and the inventory section so that you can inspect which are the items that are in inventory back of a user notice that we also have a navigation bar at the top that takes you either to the home or to the catalog and inventory sections there's also links here to go to the rabbitmq portal if you wanted to to explore what's going on with the queues and there's also links here to explore the swagger soccer ui open api documentation for both catalog and inventory service and also a few other things general links to the different technologies that were used to create the whole the whole system now before we go and dive into the catalog and inventory sections which are of course the most important uh parts of this portal at this point uh let's go back to pieces to the code for a moment and let's explore briefly the files that are available here just so that you get an idea of how this project is structured so what i'm going to do is just close this terminal for now and close the readme and the first file that i'm going to show you is package.json this one here describes all dependencies of this project which are all the node models that are installed by now and like i said these include things like react being used for all the components interactive and dynamic components use it across the portal bootstrap for layout and a bunch of things for being able to do routes in the client side the react scripts uh which are the ones that we can use to start the portal and a few other things and uh and yeah many other dependencies now let me close this and then uh take a look at the public folder here this one is the one that defines index.html which is what we call the the page template so in a single page application like i think i mentioned before there's not really a navigation into different pages of a portal there's no reload of pages there's just one page in this case in the html where every all of these dynamic components are loaded and refreshed constantly and in fact uh in this section here in this div root here is where all the javascript files uh javascript content is injected with all the react components now this file also references config.js which happens to be over here and this is a file where if you're asking where is the addresses of all the microservices this is the file so this is where you're going to see the address of the catalog service and the others of the inventory microservice right there as well as the address of the having queue portal and a few other derived address addresses for the items apis in catalog and inventory now the most important directory actually here is the search directory because this is the one that contains all the react components so this is pretty much is the heart of the of the project this is where the system logic happens and in this file if you go to in the gs this is where this is the the route where we start rendering a react components and we are asking it to start rendering them in the a root div that we just saw in in the in the html this one here we saw that there's a root div and that root div is where index.js will get rendered as you can see right here and so the first react component that we actually start rendering is this app component over here which is coming from app.js this app component defines our app by using uh first the layout component which is in charge of rendering the basic layout of the system as you can see over here if you expand components layout js this is one that defines the navigation menu at the top the container for all the other components in the middle and then the footer at the bottom back to app.js as you can see we have layout and layout defines that inside of layout we're going to have a component for the home a component for the catalog and a component for inventory so then if it goes just go into the components directory we have our catalog file and this is the one where you can start really seeing interesting things because this file allows you to communicate to the catalog microservice if you go down into the populate items method over here you can see that here is where we are actually talking to the academic service and then we're getting a response from it and that's that's the one that we are uh collecting and setting it into the client-side state that later on if you see at the bottom it's been rendered as a list as a table in the into the page okay and it's the same idea with the inventory.js which is able to render the items inventory back of a user we also have a few form well model files and form files like guiding model which is the one that is used to render the model a model dialog so you can go ahead and either create or update an item in the item form which is the one that actually shows the form inside that model and the same way we have a model for granting items for a for a user so that it can go into his inventory back so a model and a form for that same purpose and lastly we have the that vs code folder which you should be very familiar but with at this point where we also have a launch.json file where we define a defining configurations that you can use to start debugging either the server side or the client side of this portal so you can see we have a configuration for the server we have named it server this is going to be the one that can launch the npm server or the nodejs server and one configuration for launching the client at the location of the client in the browser there's also a compound configuration which i named server and client server client that can can be used to launch both the server and the client at the same time in your local box okay so i'll just close this so now let's go ahead and try that catalog section so i'm going to open the terminal once again here so our front end is still running but what we may not be running right now is a catalog service so let me go back to catalog here's my a catalog code base so i'll just switch to src play that catalog service and then i'll do dotnet run so catalog is now up and running so let's go back to the portal the browser and in order to see the list of catering items what you can do is either click in catalog in the navigation bar over there or you can click in this catalog link right here and i'll click on it and uh this should display the list of categorical guidance but as you can see that is not working right now so we cannot load the items so there is some problem happening here and so the client side one way that you can tell what's going on is by using the the browser developer tools which usually you can you can go to by pressing the f12 key which i'm going to do now f12 and this opens the developer tools section now on this one there's a bunch of tabs but the one that you're interested in is in the console tab so click on console and this is going to show you what's going on so as you can see there's an error access to fetch at https alcohol 5001 items which is the address of the cataloging service from the origin http localhost 2000 which is the address of this of the front end has been blocked by course the course policy so no access control origin heater is present in the resident resource so what is this course thing about that is going to be actually the focus of the next the next lesson so in the next lesson we will learn about cross-origin resource sharing also known as course and how it can help us enable the communication between the front end and our microservices in this lesson you will learn about cross-origin resource sharing also known as course what problem it solves and how it can help us enable the communication between our front-end portal and our mac services to understand course let's first understand what a close origin request is let's put our catalog microservice to the site for a moment and let's imagine that the node.js web server that is hosting our frontend is also the server that hosts the res apis to interact with the database that owns the catalog data in this scenario the browser initially navigates to the web server url to load the front end home page and then when the catalog section is requested the browser makes a get request to the catalog rest api to the same web server url to which the server will reply with the json representation of the catalog data the address from which the browser calls res api is known as the origin and is made of the combination of protocol host and port which in this case is http localhost it doesn't notice how the origin in the browser matches exactly the origin of the server that provides rest api let's now go back to our actual scenario where our catalog microservice hosted in asp.net course kestrel web server is the one providing the res api now when the catalog section is requested in the browser the browser makes a get request to the rest api at the origin of the catalog microservice which is https localhost 5001. since both the protocol and port of the catalog service are different than the one in the browser this is known as a cross-origin request the microservice will return the catalog data just as before but by now the browser knows that this response comes from a different origin since it had set the origin header in the request therefore it rejects a response data with a course error this happens because browsers follow what is known as the same origin policy which states that a web application can only request resources from the same origin the application was loaded from browsers and forces to prevent malicious websites from reading confidential information from other websites unfortunately this is also preventing our front end from reaching the catalog microservice so how can we fix this here's where course comes into place course allows a server to indicate any other origins than its own from which a browser should permit loading of resources here's how it works once again the browser has loaded the front-end page now the catalog section is requested and a get request is sent to the catalog microservice and since catalog is hosted in a different origin the browser appends the origin header the difference this time is that the catalog microservice has been configured with the access control allow origin heater which indicates all the other origins that are allowed to call the res api in this case this header has been configured with the origin where the front end is hosted http localhost 3000. once catalog sends the item's data back to the browser it appends this header to the response the browser now compares the value in the orient header it sent to the value in the received access control allow origin heater since they match the browser now allows the response data to reach the front end this works for simple requests like gets but for post put and other methods things work a bit differently when a cross origin request may perform some sort of write operation on the resources owned by the server like is the case when performing a post put or delete request the request needs to be first preflighted this means that an additional initial request needs to be sent to the server to determine if the actual request is safe to send going back to our scenario imagine we now want to create a new item in the catalog and therefore our front end will send a post request to the res api however since this is a post of json data across origins the browser automatically sends first a request with the options method this time not just adding the origin header but also two other headers called access control request headers and access control request method access control request method indicates that when the actual request is sent it will be a post and access control request headers tells the server that the request will come with a content type heater in this case the server should have been configured to respond with corresponding headers to indicate what it allows the headers returned by the server are access control allow origin access control allow heaters and access control allow methods if the values returned in these heaters match the values in the heaters sent in the request the browser accepts the post request and submits this original request to the server with the json payload of the new item to create the catalog microservice creates the item and returns expected 201 status code as you can see the key to a successful cross-origin request is in the appropriate course configuration on the microservice that exposes the rest api since only the microservice can declare the allowed origins but how do we properly configure cores in atheism net core that's the focus of the next lesson where we will add the missing course configuration to both the catalog and inventory microservices let's now fix the course related errors we are getting in the browser by configuring the course middleware in the request pipeline of our microservices and let's start with the catalogue service so i have the catalog codebase open here in visual studio code and what i'm going to do is open app settings the development.json first here i'm going to declare the ordering of the frontend so that we can properly configure it in startup later i'm using app settings the development.json and not absence.json because the origin of the front end is just a development server at this point and we will not need a course policy for that origin in production so what i'll do is i'll just open another section here this is just going to say allowed origin and that's going to be the address of our front end so this http localhost 3000. now that we have that let's go into our startup file and here's where i'm going to collapse the explorer for a moment let's scroll down a bit and what i'm going to do is define first a constant to represent the name of that setting that we just created so this is going to be private constraint load origin setting is going to be the name that we just created over here i'm going to copy it aloud origin right there and now that we have that we can actually configure course so to configure course what you want to do is go down into the configure method which is where you configure the request processing pipeline and so like i said this is mostly for development scenario at this point because the front end is a development web server so what i'm going to do is take advantage of this m.easy development section which only happens with the 40 minute scenarios and i'm going to add another piece over here so i'm going to say app.use course and here we're going to provide the function that configures the course configuration so i'll do builder and i'll do this and then we're going to say builder dot with origins and here we're going to specify that that origin which at this point comes from the configuration data so it's going to be configuration and here we're going to pick the right key from the configuration which in this case is allowed origin setting so remember this that this configuration is the configuration object that has been declared here right here the configuration object which is populated automatically by the sp net core runtime so that configuration object contains all the data at this point of app settings that json and upsetting the development json included allowed origin setting so you can use this to just go ahead and get the key that corresponds to the allowed origin setting that we just declared so configuration and then allow origin settings that allows the origin but we also have to tell it which headers and which methods are allowed from the client side so to do that what i'm going to do is just say dot allow any heater to allow any of the heaters that the client wants to send and we will say allow any method to allow any of the methods used from the client side including get post put and all these other verbs okay so with that we have allowed the front end origin and we have set any here and any method should be allowed okay so with that we should be able to properly invoke the methods in the microservice from the client side so let me open up my terminal once again and i'll do netrun and then i'll go back to the browser where as you remember last time we did have this course error so now i'll just refresh the page and as you can see things are loading properly and in fact if we inspect briefly the network section here and we inspect the items request that we made right here you can see that the browser did send the origin heater in the request for localhost 3000 and the catalog microservice responded with the access control allow origin heater over there which is why the browser allowed the response so that's how you configure cores and since we did this for the catalog mic service we should do the same thing for the inventory mic service so let me go back now to our inventory code base which is open here in this other business to the code instance and i'm going to do just pretty much the same thing that we just did so here in fact i'm going to copy a few sections here so from catalog i'm going to close the terminal for a moment i'm just going to copy this allow origin section into inventory cloud origin then back to catalog i'm going to copy the allowed origin setting from startup back into inventory in startup at the top i'm going to place that constant and then finally back to catalog into the configure section i'm going to copy the use course section here and back into inventory i'll collapse this for a moment in configure i'm going to add this right there okay so this enables the same a configuration for inventory as the one that we have in catalog so both microservices are properly configured now so in the next lesson we will explore in more detail all the scenarios enabled in the front end and how its react components are interacting with the microservices let's now explore in more detail all these scenarios enabled in the front end and how its different react components are interacting with the catalog and inventory mega services so i have stopped all the web servers at this point both for microservices and for the front end they're all stopped because i want to restart them in debug mode that way we can jump from client to server and see line by nine what's going on so here i am in the catalog of my service code base and i'm just going to go ahead and hit f5 to start the web server and then i'll go to the inventory maker service called this code instance and i'll do the same thing f5 okay and now i'll go to our front end and in this case instead of typing npm start from the terminal i'll take advantage of the debug configuration that we have set here so i'll go to the run on the box section on the activity pane there and as you can see we have a few options here we can debug either server client or server client server client is the one that i'm actually going to pick so that both the client and the server are started at the same time so i'll click there and this is going to bring up the browser right away however it may take a while to load while the server is compiling the source code and starting the node.js server if we head back here you can see that the server is getting started but it may take a while to start okay so as you can see the server has compiled the source code properly and it has started a debugging session of them on the front end in localhost 3000 so now we can go back to the browser and here we can go ahead and navigate into the catalog section so i just click there and then things are loading properly but how is this communication from the client happening to the server side so to understand that what we can do is just head back to play the front end and what i'll do is i'll open my explorer on the left side and i'll collapse the terminal for a moment and then i'll go into src components catalog.js let's collapse that so here the communication happens in this populate items method over there first we call the fetch function where we talk to the url of the catalog items api so that total the catalog microservice and then we get a response back from it the response will tell us the status code if you wanted to inspect that but this is actually a promise in the in the javascript land is called the promise which means that we will have to invoke the json method to actually get the items in this other 10 that we can then take and then uh put into what we call the state the state of the of this page and then that state is going to later be used into the in the render items table uh the items are going to be taken from the state into this method are received as items and then we will just render them in a normal html table so let me put a few breakpoints back into populate items so that we can see things as they go so i'll place this breakpoints over there and let's also go to the catalog microservice so that we can put a breakpoint on the server side so i'll collapse this and i'll go to items controller collapse that and then here we can go into the get async method put a breakpoint there so now let's go back to the browser and let's just refresh this page and sure enough here back into the front end we have hit the breakpoint and as you can see here's where we have the location of the catalog microservice in the items api so if i say continue that's going to talk immediately to the catalog microservice as you can see now we are in the catalog service let me collapse this a bit and here's where we're going to go ahead and talk to our mango to our repository and to talk to the mongodb database and then return the items so i'll just say continue and now we are go we are back into the front end where we have received that response which we can briefly inspect on the left side let me collapse this and that and that and as you can see we got a 200 status code which is great and then we need to convert that promise into the actual set of items so for that i'll just hit continue and now we have our list of items over here in these returned items a variable where you can see we have collected the items from the server side with the date the description the id and the name as an array and then if we just hit continue then we go back to the browser we can see that the items are right there now how about creating a brand new item so let's go ahead and click the add button here and this is the form where you can go ahead and actually create an item so again how is this form working so going back to play the front end go to the code base you're going to find the code for that in the in on the form in item form here if we go back up there's a method called create item so this is the one that's going to be in charge of sending the post request to the catalog mic service to create the item now we can do the same exercise by just placing a breakpoint over here and then we're going to get a response over there same way we can go back to the catalogue service and we can place a breakpoint into the post async method over here now back to the browser let's go ahead and create an item so let's say we're going to create in this case a shield and let's call it actually round shield and this is going to be a basic shield now what happens if i just don't put a price here so i'll go ahead and hit save and you can see that this is going to happen so we have enabled client-side validation via react into the client side so here it is making sure that i have a name and that i have a price if i don't have a price then this happens so sure enough i can put a price and that should work but before we do that what happens if i do something a bit different like putting an invalid price like a negative five if you remember the catalog service has been configured with validations and it should not allow a negative price here we have i have intentionally not enabled client-side validation for a negative number here so that it just let it go but how would that look like in the uh over here when the validation actually comes from the server side to figure that out i'll actually go back to front end and put yet another breakpoint into the catch section over here so now let's go back to the browser and try to save that now we are back into front end so as you can see we will send the request to the catalog items microservice i'll hit continue and as you can see we already got a response here we didn't even need we didn't even get to reach the controller on the microservice because the asp.net core validation runtime verified that this is not an allowed thing like the dto that we sent did not pass the validations so as you can see the response here is already telling us that this is a 400 bad request because we have sent and uh an invalid value and in fact we want to know more about what happened here what we can do is just let me put another breakpoint over here and i'll hit continue and now we can inspect this error data section here and it says here yeah one or more validation errors occur which by the way is exact same validation that we were seeing before imposement for this kind of invalid inputs and if we expand the error section here you can see that we have all the errors that are coming back from the microservices like the field price must be between zero and a thousand so this is one way that if you wanted to you can show that error with that that specific error into the client in our case we are only showing the error data that title uh property that's as much information we want to show to the client at this point so i'll just say continue then we reach the catch section which will catch all the errors here from validations or for any other kind of communication errors from the client and the server and that's going to show an alert we say continue and then back to the client this is what we're going to see good note at the iron one more validation error secured so to fix this let's actually put a correct price let's say six then i'll hit save so back to front end we'll send the fetch request and now we hit the catalog microservice because the validation succeeded so the controller is actually being hit now so this will go ahead and as you know it will execute the logic to create the item and then publish that item into the message broker and write in writing queue so that the other microservices can get notice of this so i'll hit continue then we're back into the front end and this time if we expand the response we can see that we got expected 201 and then we hit continue and back into the browser the item has been created browse shield basic shield with price six okay so what about editing an existing item so to edit an item all you have to do is click on the read button here and this will allow you to perform the edit but before actually going through the editing scenario let me actually just go ahead and remove all these breakpoints since i think we get the idea now of how communication is flowing across places so let me go to the breakpoints and just remove all of them over here and also in the catalog microservice so i'm going to go ahead and remove all breakpoints okay so now back to the front end the edit edit logic is happening if we go back into uh yeah in item form so that is happening in the update update adding method so here's where again we call the fetch method with the uh the url of the rest api plus the id of the current item so double go ahead do the fetch operation and then later we'll get a response over here so let's see how that that works in real life over here i'm going to just bump the price from 6 to and then i'll just hit save and the edit has been performed notice how things never reload here like the page is never really reloading it's just a react component that's fetching the updated data and putting it dynamically into the same page that we're always working on then we can also try the delete scenario and that happens if we go back into front end that is happening directly into the catalog catalog.js file there is a section called delete item that's invoked by that red delete button see there's going to be a confirmation then it invokes the catalog api with the id of the of the item and then it performs the delete and also it removes it from the client state so to see that in action let's go back to the client and then i'll actually like to keep this bronze shield and the other items so what i'll do is i'll create quickly another one let's just call it delete me deleting description and then i'll say price for right so i'll save this item items created and for the delete operation all you have to do is click on delete there's going to be a delete confirmation box here click ok and the item is gone and you can always confirm that these are actually happening in the server side by refreshing the browser and you can see that the items are actually gone and of course you can also take a look at the database now how about granting an item to a user which a touches basis with the inventory side so to do that what you can do is use this grant booth over here so let's say i'm going to grant this bronze shield to a user so i'll click on grant and this pops up this model dialog to grant an item now in this in this dialogue what i have done is i have made it so that anytime you open it it's going to populate some random code for some random user id remember we don't have the console of the users really here so it's just a random user id so just like we did a random user in postman now there's this page is uh presenting a random user id run good here and also there's a quantity that you can increase or decrease as as needed now this here is is happening back in in the front end is happening in the grant item form js file over here here is where uh we can actually do a breakpoint for this one uh this is where we will invoke the inventory items api uh with the data that we have about this item and then the uh inventory service is going to take care of granting the item to the user so if you go back to them to the browser and we say let's say we're going to grant two of the potion actually two of the grand brown to the brown shield to the user i'll say grant and then if you go back here in grant item form we can see that the inventory items a url is going to be invoked this time is 5005 slash items and that is going to use the user id that we specified in the client side the catalog item id which is right here and the quantity which is two and just to lose it i'm going to actually going to grab this user id i'm going to copy this one so that we can query for it later and then uh yeah i'll hit continue and that would have granted the item to the user now there's no visual representation of that completion uh in in this page but that's why we have this other page for inventory so let's go to the inventory section over here and here is where you can paste that user id and you can get inventory for the user now all the logic here is happening if you go back to to the front end this is happening actually in dumb inventory.js page so this is the page that is going to allow us to populate items based on this in on the enter user id that's going to go ahead and talk to inventory api with that user id and that brings back all the items that are in the user's inventory pack which is rendered over here in this section render items table to go back to the browser we'll just hit get inventory and there you go the current inventory for the user is presented in this case just bronze shield now once again it's also interesting to see what happens if there's an update if an update happens to this item right would the the ui be able to to reflect the fact that inventory needs to have updated data from the catalog uh when it happens would that take too much time how about that render so let's see so we have bronze shield it's name bronze shield basic shield quantity two so let's go back to the catalog and we're going to edit the bronze shield uh and we're going to change the name so instead of having it as bronze shield we'll just call it a basic shield right and perhaps we'll also update the price let's say it's nine and so so now the bronze shield is named basic shield so hit save and i'll go back to inventory and i'll query again for the items of this user that we just use a granted inventory to so hit get inventory and as you can see the name has changed to basic shield that means that as soon as we perform the update in the catalog microservice that was immediately replicated via a synchronous message into the inventory service and eventually is now able to present the updated name of the shield in this case basic shield and that happened really fast so there you go we have gone through all the sections in this basic front-end user interface so that marks the end of this model and you have connected a modern single page application built with react and hosted in node.js with your two.net based mic services to light up a basic end-to-end scenario and you learned all about cores along the way i hope you enjoyed building this system with me so far congratulations you made it till the end i really hope the course met your expectations and gave you a good sense of how to get started building microservices with a.net platform please consider hitting the like button if you got value out of this and don't forget to subscribe if you'd like to know right away when i publish new videos now microservices development is a huge topic and this course only covers the tip of the iceberg if you want to become a microservices developer and you are considering this architecture style for a real world project you will need to master many other techniques and patterns essential for distributed systems development also as you move your system to a cloud-based environment you will need to add many other pieces to your tech stack to ensure the microservices can be built and deployed quickly to scale the system to meet the production demands and to have the tools to monitor and diagnose the services when things don't go as expected to cover all these topics i created the buildingmicroserviceswith.net complete learning pad which expands what you saw in these basic skirts with dozens of additional lessons that will teach you step by step how to add all the building blocks needed for the complete microservices-based application and how to take everything to a production environment in the cloud if you are interested please check out the links below to get all the details on this premium offering thanks for watching and i'll see you next time [Music]
Info
Channel: freeCodeCamp.org
Views: 376,356
Rating: undefined out of 5
Keywords:
Id: CqCDOosvZIk
Channel Id: undefined
Length: 426min 31sec (25591 seconds)
Published: Fri Feb 25 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.