0

I want to implement a cache in my ASP.Net Web API 2. I mean I have an object called Profile with the properties UserId, SiteId, ColorTheme, etc.

I need that object for every request, I don't want to save in my database.

My question is, Does ASP.Net WebApi have something cache like a Session Object in WebForm (redis for example)?

Carlos Bolivar
  • 307
  • 5
  • 12
  • 2
    You can use Session from WebApi but it is not recommended as WebApi should ideally be stateless and adding Session breaks that. – Igor Jun 23 '17 at 20:50

4 Answers4

1

Using a session tightly couple your implementation to a detail that is not stateless (thus not restful) at all.

What I would do is to use a library which is created for this specific purpose, like CacheManager.

It will help you implementing an abstract cache which may be backed by RuntimeCaching if you plan to execute your application in a single instance, and switch any time to a distributed approach (e.g. Redis) whenever you need it.

Register inside your Dependency Injection framework something like (pseudocode):

container.RegisterSingleton<ICache<MyObject>>(() =>
    CacheFactory.Build<MyObject>(settings => settings.WithSystemRuntimeCacheHandle()));

And then inject it inside your controller:

public class MyController : ApiController
{
    private readonly ICache<MyObject> _cache;

    public MyController(ICache<MyObject> cache)
    {
        _cache = cache;
    }

    public IHttpActionResult GetCached()
    {
         var myObj = _cache.Get("myKey");
         if(myObj == null)
         {
             myObj = GetObjectFromWhereverYouWant();
             _cache.Put(myObj, "myKey");
         }

         return Ok(myObj);
    }

More examples are found inside the documentation.

Federico Dipuma
  • 17,655
  • 4
  • 39
  • 56
0

ASP.Net Web API 2 follows REST pattern and per the pattern it should be stateless but yes you can use any caching mechanism to store the object. I have used Redis with Web API for this same purpose. Session should be used cause it breaks the patern. Httpcontext.Cache whether is supported not sure of. See the below posts

How to use caching in ASP.NET Web API?

https://code.msdn.microsoft.com/Caching-In-Web-API-cb40be30

Rahul
  • 76,197
  • 13
  • 71
  • 125
0

If you really really need a cache that looks like a solid solution - http://blog.developers.ba/simple-way-implement-caching-asp-net-web-api moreover, you can use Session by adding

protected void Application_PostAuthorizeRequest()
{
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}

to your global.asax, although this can seriously damage the preformance of your web app.
Web API is designed for REST implementations, and one of the key points of REST architecture is statelessness - you should not have a session, you should send a security token with all of the required user information on each request. If you work this way you will find the framework playing to your hands a lot more easily because thats what it was designed to do.

Yuval Perelman
  • 4,499
  • 1
  • 22
  • 32
0

Are you sure you don't want to use your existing database? Do you have peak traffic or scale that mean generating the profile from the system of record on every request is actually problematic? Without more info it is hard to know but if it were me I would hesitate jumping straight to session stats or in memory caching as both add complexity.

You could consider putting a simple solution into production without caching or session state, using your existing db, and measure if it needed improving?

Assuming you do need something faster than the database, I would cache the user profile in memory using an open source library called LazyCache that will do this caching for you in two lines of code. It is also available on [nuget][1].

// get the cache (or use dependency injection?)
IAppCache cache = new CachingService(); 
// get the user from cache or create their profile
var cachedResults = cache.GetOrAdd("CacheKey", () => GetUser(userId));

It has built in locking by default so the cacheable method will only execute once per cache miss, and it uses a lambda so you can do "get or add" in one go.

(Disclaimer: I am the author of LazyCache)

alastairtree
  • 3,960
  • 32
  • 49