NamespaceSystemLibrary.Common.Web SystemLibrary.Common.Web.dll
Caching for web applications
Default duration is 180 seconds
- configurable in appSettings.json or per Get() invocation
Auto-generates a cachekey for you if you don't specify one
- the flag "IsAuthenticated" is added to the cache key so it varies based on either logged in or logged out
- if IsAuthenticated is true and user's identity is of type "ClaimsPrincipal", it adds all roles to the cache key
Optionally, you can skip cache by setting parameters:
- skipForAuthenticatedUsers, false by default
- skipForAdmins, true by default
- true if current principal is in either of these case sensitive roles: "Admin", "Admins", "Administrator", "Administrators", "WebAdmins", "CmsAdmins"
- skipFor, your own implementation which returns true to skip
Cache
public static class Cache
Inheritance
Examples
Configure the cache in appSettings.json
{
"systemLibraryCommonWeb": {
"cache" {
"defaultDuration": 180,
}
}
}
Arguments
Methods
Get data from cache, or add it to cache before it is returned
Note: null is never added to cache
public static T Get<T>(Func<T> getItem, string cacheKey = null, TimeSpan duration = default(TimeSpan), Func<T, bool> condition = null, bool skipForAuthenticatedUsers = false, bool skipForAdmins = true, Func<bool> skipFor = null, bool debug = false)
Simplest example:
var cacheKey = "hello-world-key";
var data = Cache.Get(() => {
return "hello world";
},
cacheKey: cacheKey);
//'data' is now 'hello world', if called multiple times within the default cache duration of 180 seconds, "hello world" is returned from the cache for all non-admin users
Example with multiple options passed, and a condition that always fails:
var cacheKey = "hello-world-key";
var data = Cache.Get(() => {
return "hello world";
},
cacheKey: cacheKey,
duration: TimeSpan.FromSeconds(1),
condition: x => x != "hello world",
skipForAuthenticatedUsers: false);
//'data' is equal to 'hello world', cache duration is 1 second, but it only adds the result to cache, if it is not equal to "hello world"
//So in this scenario - "hello world" is never added to cache, and our function that returns "hello world" is always invoked
Example without a cache key
namespace: Company.Services
class CarService
{
public string GetCars()
{
return Cache.Get<string>(getItem: () => {
return HttpBaseClient.Get<string>("https://systemlibrary.com/api/cars?top=1");
},
skipForAdmins: false);
}
}
//Note: This will cache the top 1 car for everyone, even logged in administrators/admins because we set 'skipForAdmins' to false,
//If we should set skipForAdmins: true, then administrators would always invoke our method, the data would never come from cache for those users
Example without a cache key and with 'external' variables
namespace: Company.Services
class CarService
{
public string GetCars()
{
var url = "https://systemlibrary.com/api/cars";
var urlQueryValue = "?filter=none";
var top = 10
//urlQueryValue could be an input variable to GetCars()
return Cache.Get<string>(getItem: () => {
return HttpBaseClient.Get<string>(url + urlQueryValue + " top=" + top);
});
}
}
//GetCars returns response either from the API, or if called upon multiple times within default cache duration of 180 seconds, it would return the data from cache
//Note: cache key is created with the outside variables (converted using .ToString(), so a class, 'User' for instance, would just be .ToString'd and not differentiated on properties like emails/firstname, etc...)
//Note: cache key would look like this: Company.Services.CarService.GetCars__uniqueLambdaBackingName_https//systemlibrary.com/api/cars?filter=none10
//Note: cache key for an authenticated user would minimum append 'true' to the above cacheKey, and if it is a ClaimsPrincipal user, it would append all roles that user belongs to
Generic types
Name | Description |
---|---|
T |
Methods arguments
Type | Name | Description |
---|---|---|
System.Func<T> | getItem | |
System.String | cacheKey | Set to null if you want a cache key auto-generated for you |
System.TimeSpan | duration | |
System.Func<T, System.Boolean> | condition | Add to cache only if condition is met, for instance: data != null |
System.Boolean | skipForAuthenticatedUsers | Skip cache for any user that is authenticated, but is not part of any of the admin roles: Admins, Administrators, WebAdmins, CmsAdmins |
System.Boolean | skipForAdmins | Skip cache for current principal that is authenticated and is part of either of the roles: Admins, Administrators, WebAdmins, CmsAdmins |
System.Func<System.Boolean> | skipFor | Implement your own logic for when to skip cache, let it return true on your conditions to avoid caching |
System.Boolean | debug |
Type | Description |
---|---|
T | Returns data either from cache or the getItem() method |
Get data from cache, or add it to cache before it is returned
- Auto-generates a cacheKey based on input params
Note: null is never added to cache
public static T Get<T>(Func<T> getItem, TimeSpan duration, Func<T, bool> condition = null, bool skipForAuthenticatedUsers = false, bool skipForAdmins = true, Func<bool> skipFor = null, bool debug = false)
Example without a cache key
namespace: Company.Services
class CarService
{
public string GetCars()
{
return Cache.Get<string>(getItem: () => {
return HttpBaseClient.Get<string>("https://systemlibrary.com/api/cars?top=1");
},
TimeSpan.FromSeconds(5));
}
}
//Note: This will cache the top 1 car for everyone except 'Administrators' for 5 seconds
//If we should set skipForAdmins: false, then administrators will also get cached content
Generic types
Name | Description |
---|---|
T |
Methods arguments
Type | Name | Description |
---|---|---|
System.Func<T> | getItem | |
System.TimeSpan | duration | |
System.Func<T, System.Boolean> | condition | |
System.Boolean | skipForAuthenticatedUsers | |
System.Boolean | skipForAdmins | |
System.Func<System.Boolean> | skipFor | |
System.Boolean | debug |
Type | Description |
---|---|
T |
Get data from cache as T
- returns default if cacheKey is null or empty
Returns default T if cacheKey do not exist in cache, else T
public static T Get<T>(string cacheKey)
Simple get object from cache based on a cache key:
var cacheKey = "hello-world-key";
var data = Cache.Get<string>(cacheKey);
//If 'hello-world-key' exists in cache, the variable 'data' now holds that value
Generic types
Name | Description |
---|---|
T |
Methods arguments
Type | Name | Description |
---|---|---|
System.String | cacheKey |
Type | Description |
---|---|
T |
Get data from cache, or add it to cache before it is returned
Note: null is never added to cache
public static T Get<T>(string cacheKey, Func<T> getItem, TimeSpan duration = default(TimeSpan), Func<T, bool> condition = null, bool skipForAuthenticatedUsers = false, bool skipForAdmins = true, Func<bool> skipFor = null, bool debug = false)
Example with a cache key
namespace: Company.Services
class CarService
{
public string GetCars()
{
var cacheKey = "car_service_get_cars";
return Cache.Get<string>(cacheKey, getItem: () => {
return HttpBaseClient.Get<string>("https://systemlibrary.com/api/cars?top=1");
},
TimeSpan.FromSeconds(5));
}
}
Generic types
Name | Description |
---|---|
T |
Methods arguments
Type | Name | Description |
---|---|---|
System.String | cacheKey | |
System.Func<T> | getItem | |
System.TimeSpan | duration | |
System.Func<T, System.Boolean> | condition | |
System.Boolean | skipForAuthenticatedUsers | |
System.Boolean | skipForAdmins | |
System.Func<System.Boolean> | skipFor | |
System.Boolean | debug |
Type | Description |
---|---|
T |
Create a 'lock' to part of a function, to run it only once within the duration
Returns true if the key do not exist or has expired else returns false
- Default lock duration is 60 seconds
Useful to execute code only once within the time frame per app instance
NOTE: Uses the stack frame to read current namespace and method as cache key, so max 1 invocation per function scope, else you must fill out the cacheLock parameter too
public static bool Lock(TimeSpan duration = default(TimeSpan), string lockKey = null)
Example
if(Cache.Lock("send-email", TimeSpan.FromSeconds(60))
{
new Email(...).Send(); // Pseudo code
// Example: invoking this code 66 times, one time per second, where first invocation is one second from "now", will send two emails: one at second 1, and another at second 61
}
Methods arguments
Type | Name | Description |
---|---|---|
System.TimeSpan | duration | |
System.String | lockKey | Append data to the lock key, if multiple locks resides inside the same method scope |
Type | Description |
---|---|
System.Boolean |
Remove a single item from cache based on cacheKey
- If it does not exist, it does nothing
- If context is not web, it does nothing
public static void Remove(string cacheKey)
string removeCacheKey = "hello world";
Cache.Remove(removeCacheKey);
Methods arguments
Type | Name | Description |
---|---|---|
System.String | cacheKey |
Add item 'obj' to cache for a duration
Defaults to 180 seconds cache duration if not specified
public static void Set<T>(string cacheKey, T obj, TimeSpan duration = default(TimeSpan))
Generic types
Name | Description |
---|---|
T |
Methods arguments
Type | Name | Description |
---|---|---|
System.String | cacheKey | |
T | obj | |
System.TimeSpan | duration |
}