Response caching using Redis | ASP.NET Core 5 REST API Tutorial 25

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm Nick and I'm gonna show you how you can start using readies to catch responses in any speed that color in this video I won't be going in depth in what Redis is and what caching is I'm kind of assuming you know what it is but to boil it down in a sentence caching is when you don't go to the database or the disk all the time to get some values that might be slow to get you just put them in a temporary place and you just go to that place because it's faster to go there if you do want me to make an in-depth video on caching and read this please leave a comment down below and subscribe and I will make a video for that if that will exist it will be linked right now in the top right corner of your screen so if you from the future just click on that and it will be there so let's dive straight into the implementation first we will need a package and that package is a Microsoft package because we will be using the a speed know that called between approach the package name is Microsoft dot extensions that caching the stack exchange radius so we'll be adding that into my project and what this project adds is the I distributed cache interface but even though that in the face exists we make our own interface to wrap around that because we don't want all the features we want some of the features so what I'm gonna do now is I'm gonna say I response cache serves and we will need implementation of that as well so let me just copy that because I'm lazy and I'm gonna do that I'm gonna say I response cursor and we have our service and I will you need to create a new installer and this will be the cache installer so cast installer if you don't know why we're doing this installer approach instead of adding it in the startup you will find the link right now in the top right corner of your screen go watch that video but essentially we're splitting it in different classes so we don't have it cluttering a single file so that is here and it's very easy to set up we can just save our Redis cache settings and this class doesn't exist but we will make it because we need some settings so ready cash settings I won't be using the building option this one we're gonna make our Road I'm gonna say configuration dot get a section and we're gonna use that name off already scan settings this is what the name of the object will be in our app settings dot Jason I'm gonna add it right away so bind this already scan settings and then add it as a single in case we need to inject it anywhere so add single common already's cache settings I go ahead and make this plus I'm gonna make a cache folder here so directory cache directory created and I'm gonna say new class readies cache service and what are we gonna add here is just a few properties we can add a boolean and we're gonna say enabled so whether if I type it properly yeah and this indicates whether already's cache is enabled or not and we also going to add there readies cast connection string so I'm going to name it connection string so that's here let's import it so we have that and let's go ahead and say if Redis cast settings is not enabled then return at this point because we don't want to do anything else if it is then we're going to use that extension method that this packet we just added gives us and that is the add stack exchange Raley's cache and we're gonna say options and then options that configuration equals reddit cache dot connection string and on top of that we're going to register the interface and the service we just created so add singleton I response cache service and then response customer service and that's it in terms of di stuff so we can close that now I do need to create these in the app setting so let me just that's real quick I'm gonna make an object called reddish cash settings and then this object has two properties a boolean called enabled and that will be true and a connection string and that will be localhost that's all you need there's no keys or whatever this just indicates where the seller lives so there's that now let me just go to the controller and take a look there and see what we want to cache I'm gonna use the post controller as an example so you don't want to catch the responses of update or delete or create because these responses just dynamic depends on the thing just manipulated but get for example like get all or get a specific one by ID those ones can be cached especially in a blogging platform because those blogs or post don't change so regularly so you can just go get them from any memory cache distributed in memory cache done the database over and over again at putting the stress in the database you just put it in a thing that can cope with it way easier so those two endpoints are the ones we will be caching now there are many ways to go about this the one I would go is using an attribute and this is very similar to how we did API key implementation you'll find a card for that as well it was the previous video at this point I can actually show you how this will look like so I can just pretend I have an attribute called cached and then it will accept the minutes we want this to be cached for so in this scenario in fact you can actually go lawyer you can just use seconds so in this now we're gonna cash it for like 10 minutes so 600 seconds and I'm gonna go ahead and do the same for that get all one and now in the cache folder we're gonna create a new attribute called cached attribute and this attribute will need to extend the attribute class to be used as an attribute of course and also the ia sink action filter which gives it the filter the middle type of functionality and as we said before we need to change to a sink we don't need to but we aren't going to because we need to avoid stuff and the way this works is we have the before so as the thing is coming in the middle where you have stuff you can do to the request before it actually goes to the next Midway then you can say next and this is where it's being moved to the next maybe where in this case the controller and then you have the after we need to do stuff thinking both before and after yeah it's both before and after so I'll show you how also middleware works in the scenario where you manipulate the request before it goes to the controller and after it went to the controller before I show you that I should also restrict each usage so the attribute usage should only be able to be used on the class level and the method level and what we also need is a private read-only end and that's them time-to-live seconds and that's for how many seconds the request will actually be cashed in readies cache are we going to initialize that from the constructor so we have our cast attribute we get that and we're going to use that in the caching mechanism now let's see what the serve is this cache service needs to do and that's no place attribute it's the service that we created before so let's go to the interface and let's say what do we need we need two things we need to be able to cache links or put them in the cache and we also should be able to retrieve things and because we're dealing with responses here the responses just strings with specific content types so we will be caching strings Redis ultimately accepts bytes but we'll be converting that so gonna create the task and I'm gonna say cache response async and we give it a cache key which is the way we do our lookup in Redis and then an object so the response object and also a timespan and this is the time to live and then to retrieve it back we will be getting a string back and we'll be doing the serialization later so in fact we don't even need to digitalization because we can just return the string I will say get cache response async and then to do that lookup we need the cache key of course but that's all we need nothing else so let's go to the implementation and just implement the missing members and let's see how these methods should look like so firstly we need to inject the I distributed cap which is the only reason we added this stack exchange reddy's so private read-only I distributed cache and with that inject it I can actually show you the methods in this interface the point if you have set refresh remove and then the a single ins but we don't need remove and we don't read refresh so we'll only expose a friendly API for our attribute not this very generalized I add distributed cache so let's see how the caching would look like like taking the response and putting it in the cache I'll string well first we would say that if response is null then let's just return at this point there's nothing to cache if the response is null and then we can serialize the response so I'm gonna say serialized response equals Jason convert and then we gonna do serialize object and we gonna get the response object as a string essentially and then we can say a weight distributed cache now why do you need to change this one async method to use a weight distributed cache and I'm just gonna set a string guessing there's this extension method here but what comes with the package and you just say cache key and then the serialize response and then we also going to use the method overload that allows us to pass this divided cash option and that's because we need to have the time to leave there and that is an a property on the object and this property name is absolute exploration relative to now so you give it the time span from now to whenever you want it to be expired so in this and I will be ten minutes I'm gonna say time to live and that's it for the caching method the retrieval is even simpler all we need to do is say var cached response equals our weight distributed cache don't get a string guessing and then just use a cache key and then of course it'll change this to an async method and then say return a string dot is null or empty and check the cached response what the response is not or empty then return null else return the response itself and that's all we need for the response caching service some cannot close that now because we don't need anymore and I'm gonna go it's just import this here so this is what it would look like and now let's go to the attribute and implement the attribute which is the most interesting part of this so as we said we have before the controller we have send it to the controller and we have after the controller what we need to do we just use comments to show you is check if request is cached then if it is just returned here so if through return if false move it to the controller and then afterwards get the value cache the response so essentially what this does is the first request will be cached and than any other request for the specific thing we we retrieved from the cache for the next ten minutes and then another request will cache it again and it goes on goes on and we only hit the database once instead of hitting it on every single request so that's what it is so the first thing we need to do is we need to see if caching is actually enabled so that the attribute might be there but you might have turned off caching you don't want to use it so we're gonna get the cache settings are you gonna say context dot HTTP context dot request services dot get required service and had some comments on why I'm not injecting them from the attribute constructor is because if you are to inject those like if I if I did private read-only I response cache service here and I added in the constructor then I would need to inject it wherever I give the attribute the problem with that is that you cannot use the object here because it's just not allowed so I wouldn't be able to do that I'm getting it from the request which is still coming from the DI container using all the lifetimes you've said it's just not injected this makes testability a bit trickier but again as I said in the previous video I will show you how we can unit test all of that in the future so subscribe so I will need this response service in fact at this point I will actually need there already cache settings but we do need the service itself so now you have the service with the settings I can say cache settings dot enabled and if it's not enabled then I wait next so sent to the next controller and return in fact it's the next mid way but if that checks out then we can get the cache service and again we can do that from the same way let me just copy that and say I responds cache service so we have our car service here and what we do need at this point to identify each request as unique is a cache key remember I'm only doing this forget endpoints so what I'm gonna do is I'm gonna get the actual URL of the endpoint and then I'm gonna get the query string parameters I'm gonna order them by name and I'm gonna use that as a cash key that reason why I'm doing the ordering is because if they come out of order you wouldn't want to catch this as a different thing it's the same thing so let's see in practice how this looks like we have a var cache key and this will be coming from a method called generate cache key from request and I'm going to use the request from the HTTP context and let's create this method here in this class so what this returns is a string and let's see how the implementation looks like all I need is the URL and the query parameters so because I'll be doing mutations on a string I'm going to create a string builder because strings are immutable and we're creating a new objective time we create a new string go manipulated so I'm gonna make a string builder for that I'm gonna say key builder equals new string builder and then the first thing I need to add is append and I need to add half of the request so in this case it's request dot path and that's enough and then I need to iterate over all query string parameters but they should be ordered to prevent duplication in terms of keys so I'm gonna get the query and I'm gonna order by the key and this query has all the values of the query string as separated things in a dictionary or key value pair and I'm gonna use the contractor here so I'm gonna say key and value that's because key value press gonna use like that and all I need to do is say key builder dot append and I'm gonna append let's use this pipe symbol here so 5 key and then - value there's no reason why you should follow this approach it's just you need to somehow separate them and make it readable as well so I think this works and at this point we can just say return dot key builder dot - string and we have a cache key and we can actually make this static as well so now we have the cache key the next thing we need to do is check if the cache response exists so cached response equals a weight cache service dot get cached response I think using that key and we need to do a check wanted to say if spring is not null or empty in that string is a cached response then we need to essentially return it how do you return from here well first we create a Content result because you need to return some type of result and because it's a string is not an object we need to do this manually so content result and there's three things you need to set here oh by the way I should also mention that we only do that for getting points that return requests 200 if you need to use somewhere else please modify it yourself I won't be showing that I will only be showing for 200 so at this point we have the content which is the cached response then we have the content type which in this scenario REST API will change Jason so I'll say application Jason and last but not least the status code of course you could cache all those values if you really wanted to in your cache object I won't be doing that but if you need to make it flexible it would be a good idea to cache everything and through 10 we need to say context dot result equals our content result and this will use the response from Redis and then return it to the user now let's see what happens next if it's not in the cache it will go and get it from the controller but then we want to cache it so that other requests get it from the cache so I'm going to say a var executed context equals whatever comes from the controller's manipulation I'm gonna delete that and I'm gonna say if executed context dot result is okay object result are we gonna extract that doesn't like a uptick result then just cash it so how do we do that we say cash this dot cash responds async we're gonna use the cash key we already created and we can say okay object result dot value and then the timespan will be not 0 it will be coming from seconds and it's coming from the time to live in seconds the reason why we have a time to live is because we want our cash the value to expire if a specific times past now the sonars way you never expire it and you updated reactively whenever the user updates the post you can do that as well I just showing you a very generalized way of doing this but this is everything we need to get it's working now on top of that we also need I read this cash running so I will run it in docker and that's the commands docker run I'm going to specify the port I want it that's the default port and then reddy's so let's just run that and you can see that it's running because I'm using this here we go I'm using this browsing tool called Redis Desktop Manager and you can see all the 16 databases of reddy's here by default is using the 0 1 which is the default so that's the one our API will be using and let's run the API and see what happens so I have a key already so I'm going to use that to allocate and now I should be able to get all the posts now let's see that already cache is empty again I'm refreshing there's nothing in the cache but now when I do execute see I get this value but if i refresh that you can see that we have the data cached here and that's everything that's a response so if I run it again you can see it's coming again with all the content types and the response types and everything and as many times as I click it and this is now coming from the cache it's not actually hitting the database and I can show you that in the console because if I expand that you can see that the first request is going to the database to get the post here but anything after that is not calling it even though it's the same in point what you can also see is that from the first call that goes to the database now this is a bit exaggerated because it's the first call to the database so it would be quite long but normally you'd find this request to returns around forty milliseconds or thirty to forty milliseconds now the time is more like 10 812 so it really cuts down the time it takes to do those calls if you catch them in Redis last but not least I will show you also how to add this in your docket compose because now your API needs it it's very very simple so if I just do docker compose here let's just add it first we need to say that our main API depends on race I'm gonna put Redis here and then I'm gonna say Redis which is the container the image name is of course Redis then I can also say container name again Redis and ports I'll use the default but you can change them if you want to so 63 79 for both so this is all I have to show you for today leave a like if you liked this video subscribe for more content like this and i'll see you in the next video keep coding you
Info
Channel: Nick Chapsas
Views: 47,013
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, asp.net, .netcore, dot net, core, C#, how to code, tutorial, asp.net core, javascript, js, 2.2, csharp, rest, rest api, development, lesson, software engineering, dev, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, asp.net core 3, response caching asp.net core, response cache, redis cache, redis, web api, dotnet, .net
Id: KboCpJGa9ag
Channel Id: undefined
Length: 23min 33sec (1413 seconds)
Published: Thu Aug 29 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.