The NEW caching you should be using in .NET 7

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick and in this video i'm going to introduce you to the brand new output caching added in.net 7 and explain how it is the future of caching your responses for your asp record applications now this is not to be confused with the existing response caching that we did have for a while now this is a separate thing and i'm gonna explain how they differ and i'm gonna show you how this brand new output caching is absolutely fantastic and packed with features you wanna use and you will definitely be using to do some really really cool and flexible stuff with caching the output of your application if you like a lot of content and you want to see more make your subscriber in this notification bell and for more training check out nickjabsters.com now just a quick reminder that i will be running my in-person workshop introduction to effective testing in c sharp and dot net in a bunch of conferences this year for now it's gonna be ndc oslo ndc sydney dot net days in romania ndc minnesota and nbc london all the data on your screen and you can use the links in the description if you want to get a ticket and come and learn with me in person and now back to the video now before i check the code i want to explain the motivation of why they did that in the first place because we do have already response caching we had it for years now however there's an issue with how that is implemented that was implemented and designed to respect the standard http caching semantics that means that if you have a no cache header in your request then the server will respect that and bypass the cache and if you wrote your application in a way that you don't want the cache to be bypassed well tough luck because that type of caching was designed with those headers in mind the no cache is only one of them there's many cache related headers that the response caching could respect and do stuff with the new output caching is completely different instead of checking those http headers to determine whether it should or should not be cast or should be returned from the cache or not the application directly has all the logic for its own output and that is great because the previous response caching lends itself better as something that could be used by a proxy like yap or nginx and all those services however when you want application level output caching that didn't really fit the use case so let's see how we can now implement output caching in our application so what i have here is a simple api i'm going to show you all the code it's basically crap but i didn't bother adding the delete because i can demo everything without the delete endpoint but if i go ahead and i debug it this is using a real database i can go to postman and i can list all the customers in the system and as you can see i have a few people in the database in fact let me just show you that this is a real database and these are real users in a running postgres database and i can go ahead and get a user by id over here and as you can see user is returned i can also create a new user and give it a different date and then if i create that user is created you can see them listed over here i can get them i can also update them if i want to we're gonna see all of that in this application and also what i can do is i can say that if the name matches part of their first name then i want only those users to return so if i say sas nick chapters and chip naxus are returned but nothing else is returned so i also have a filter for this endpoint now database calls like this in a small database are very fast however as your application scales you might not want to call the database every single time and in fact why do all the compute anyway if the user is still the same and it hasn't changed then just return something from the cache and this is where we're going to introduce the brand new output caching so it is extremely simple to get started all you need to do is first say builder.services.add output cache on your service layer and then from the point where you want the caching to start because remember this is a middleware so if you have swagger or authentication before you might want to put it before the start of your caching but you can also use mechanisms to buy past caching for those services and we're going to see them as we go but all i need to say is app.use output cache and that's it you got started now if i simply do that then as you can see over here if i stick a break point to this and i go and i call the get all endpoints the end point is hit because we're coming in that method but if i call it again it is hit again because i didn't actually tell anything to be cached by default just because you added the service in the middleware it doesn't mean that something will be cached now the simplest way to cache something is do the following you can go to the end of this method in this case and say cache output and that's it we don't provide any configuration any time span anything this basically tells it cache it effectively indefinitely now so if i go back here i'm going to add a breakpoint go to postman call that then the first time it's not cached comes in and it is now cast so if i call it again the breakpoint is not hit because this response including the headers the body everything all that comes from the cache and you also have this edge header indicating for how many seconds this thing has been cast for so you can see as i go that it's also increasing so it's doing a lot of work for me behind the scenes now i should mention here i'm not going to show you in this video how to do this but you can also plug something like a distributed cache like redis to cache that in a centralized place for now i'm going to show you everything in memory just for the sake of simplicity of the demo now in this case i went and i added a policy on a specific endpoint but you can actually customize the way the policies work on the add output cache level i can do this and i can get an options object and i can say for example here add base policy and this base policy is me explicitly saying for example by default that nothing should be cached by default now this is the default behavior anyway but you can also customize this in any way you want for example you can say that if you have a request with and i can have a predicate here again and i can get data from the http context so if there is a request where it has a specific i don't know query string parameter now you should realistically not do that because people can bypass your cache but if there is a a request that says no cache in the header and that value is true then no cache and this will now allow you to have no cache if a question parameter with value true is there you can also do other things for example with the path if is under a specific path for example under your css or your javascript you can also have a no cash policy now you can also specify pre-baked policies as well so you can have an ad policy here and say that they have a no cash policy and then this no cash policy is a simple no cash on that's it which means that i can now go to my get endpoint over here again and i can say output cash and i can give it a policy name and i can specify no cash here and if i do that if i have an overarching cash policy but this has a no cash then the cash will be circumvented that we won't actually cash anything here you could of course as well have the predicate here so if you wanted no cash here you could also say no cash but having it as a policy that is predefined makes it easy to be reused everywhere and you could also skip the extension method altogether and say output cache using an attribute that we have now and you can say either no store true or policy name no cache and this would also work just fine now here's another very interesting feature because i have a query string parameter over here called name i want that to be my differentiator when i'm caching something for example i want to have a different cache results that when name is sas and different cache results that if the name is nick for example so i can go here and i can say cache output and i can say very buy and then i can specify what i want my caching for this endpoint to be varied by i can have a header i can have a query parameter or i can have a full-fledged value which gets the full http context in here i'm just gonna do very by query in my case and i'm gonna say my query key here is name which is my query key value so if i take a break point here now and i go if i go ahead and i call the get everything endpoint then i'm getting a cash but when i hit it again i'm getting a cache hit meaning it is being returned by the cache now if i add the name parameter and i say sas i'm getting a new request in here and that is now caching based on that query string parameter so if i call again i'm getting that results that cached if i remove it the previous thing is still in the cache because i have this variation now if i say nick for example in the name i'm getting a new cache hit because that is a whole new bucket of requests being cached here and if i call it again and nothing is removed by the way unless i specify and i could specify it i could say expire and i can have a time span and i can say from milliseconds and have 5000 meaning that if i go in and i run this let's see how this works then i call that first time it is cached second time third time coming from the cache now five seconds will pass and the cache was expired and now i can go in again and re-cache it so it's very flexible you can chain mechanisms as well if you want it's very useful when you want to make a single policy now here's where this gets even cooler having definite caching over here and i'm gonna go ahead and run this application and then get all the users the first time i'm caching everything and then the second time everything is coming from the cache if you can see here i'm not really hitting that breakpoint anymore however if i create a new customer over here then as you can see that customer is not returned right everything you see is still the precached data however if i try to get them with their id over here they exist in the system but i'm still getting the old data which is bad because well how do you update your cache if you're in definitely caching something well here's the cool thing what you can do is you can actually say over here tag this with a specific name in this case i'm going to say just customers so i'm tagging this output set with a specific tag meaning that i can now if i want evict that cache by tag name so i can say i output cass store and i can get access to the store itself and let's grab a cancellation token because we're going to need it and now when we create a user what i can say is cache.evict by tag and my tag is the customers so i can say evict that cache that matches that tag name so let me quickly just delete the user i just created from the database to demonstrate this again so now i'm going to stick a breakpoint here and also stick a breakpoint here and just quickly run this so let's go back to postman try to get all the users and as you can see now we're hitting that end point and we're getting all the users one two three four then i'm going to go ahead and recreate that specific user and as you can see this will now call that customers evict by tag a sing and now if i go back to the users i can get the cache again because i evicted that cache and it's being rehydrated and new on the next request which is absolutely fantastic and you can use that eviction mechanism to evict other things for example in this use case where we're caching by id we also have a bit of a problem here and ideally i'd like from microsoft to somehow make it possible without having to make a policy i haven't found a way to do that but basically here i can say cash output and i could technically give it the same customers tag and make sure it's evicted alongside the creation of any new customer but the creation of a new customer doesn't really affect the existing cache it only affects the get all endpoint and all the other customers that are cast individually are still absolutely fine so what we can do to be smart about it is create a new cache policy i'm gonna call it a buy id cache policy and that's gonna be a full-fledged class it's gonna implement the i output cache policy i'm gonna implement the three methods we need here and now i have already implemented this outside of this video i'm just basically ripping off the default cache policy and i'm adding a small thing in it so i'm going to show you what it is here we go and by the way this is very scrappy this is just to demonstrate the point but effectively what it's doing is it is getting the id route value which is this one over here and it's using it as a tag and if this tag then it's evicted only that cache is removed from the in memory cache so what i can do now is i can say hey cache this for individual ids and i can say x add policy by id cache policy over here and then all that logic will be triggered every time and it will determine how my cache is used and i can go back to the update endpoint over here and say after the update let's go ahead and add the output cache store and the cancellation token over here i can say await cash dot evict by tag and my tag in this case is the id to string and then the ct meaning let's just bring all that together now let's stick a few break points we're going to go ahead and run this meaning that if i go here get all the users get chip nexus and i go ahead and i get that user by id then as you can see first request is hitting the end point over here absolutely fine then any subsequent request does not because this thing is cached and then if i go ahead and i update that user to be called something else in this case let me make sure i have the right id yes i do then i'm going to evict the cache of that specific id value meaning that after the update if i go ahead and i want to get that user the cache has been evicted and i did it in a bit of a hacky way but i'm only invalidating that specific cache for that specific customer in my system which is very very efficient now one of the problems you might have when you have caching like this is cached unpaid or thundering head what does that mean well if i go ahead and i paste this code over here then what you have here is a lock end point that waits for a second so it's doing some work it's simulating it's caching for a shorter amount of time that the time it takes to actually run the work and have also turned off locking by default it is on but i just want to show you how this works so i'm going to go ahead and run this and i'm going to bring the browser in because postman won't let me do this rapid fire movement so i'm going to bring my browser here and call that lock endpoint once it is waiting for one second and then it is returning well at zero because the count was zero and later was incremented now imagine you have many users coming to your endpoint let's say five in one second and you're caching something that takes some work to be completed then if i do this one two three four five very very quickly all five requests actually went in and they did the work in the method this is an example of the problem i described where many people come in and they invoke the same cache before the work of the cache is actually finished meaning that the work will be done many many times until that first time that it will be cached however with a default behavior which is allow locking true and you don't have to have this here it will be true by default then if i go ahead and i debug this and i go back here and i call it once you're gonna see zero but now if i do five times one two three four five you only see one because that method was locked for the duration of the request so it was only cached once but at least now you know that you can also disable it if you want to now the last thing i want to mention is that you also have support for the if none much and the if modified since headers the if not much has to do with e-tags and i don't want to dive into e-tags because there are a whole different topic in themselves and i want to cover it individually however the idea is that you can tell the application to not give you the customer back if you already have that same version of the customer locally and the e-tag changes every time your customer in this case would change so you put it in the header and you say it would look something like this you go to the headers over here and you say if none much and then you have the etag which can be anything it's not necessarily the customer id in fact it is not the customer id it is a value generated every time the user has changed but you can say something like this and if the value was actually matched you'd get the 304 and it's the same with the if modified since you can have a date here and say if this value has been modified since a specific date and time then give me the new one otherwise tell me it wasn't modified i won't dive too deep into those they they do deserve their own video but just know that they are supported so this is just a quick overview of everything we have in here i hope you like this feature it's very very good to see that they're finally adding this because it does solve a lot of the problems we had with response caching and i can't wait for this to be out to actually use it well that's all i have for you guys thank you very much for watching special thanks to my patreons make this video possible if you want to support as well you can find the link description down below leave a like if you like this video subscribe for more like during the bell as well and i'll see you in the next video keep coding you
Info
Channel: Nick Chapsas
Views: 73,649
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, dotnet, .net, .net caching, caching, cache, output cache, response cache, response caching in asp.net core, response cache asp.net core, c# response cache, output caching in mvc, output caching .net, output caching asp.net core
Id: 0WvGwOoK-CI
Channel Id: undefined
Length: 18min 16sec (1096 seconds)
Published: Mon Jul 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.