-2

public class CacheController
{
    public IMemoryCache _memoryCache {get; set;}

    public string getCacheMethodOne(string token)
    {
        string cacheValue = null;
        string cacheKey = null;

        if (!_memoryCache.TryGetValue<string>("123456", out cacheValue))
        {
            cacheValue = token;
            cacheKey = "123456";

            var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(2));

            _memoryCache.Set<string>("123456", cacheValue, cacheEntryOptions);
        }
        return cacheKey;
    }

}


Problem with this line of code: string otp = new CacheController().getCacheMethodOne(ClientJsonOtp.ToString()); throws exception.

Object reference not set to an instance of an object.

Should i create new instances of IMemorycahce. If i do so, will it affect the cache. as it may lose the previous cache instance.

try
{
    var finalResult = result.Content.ReadAsStringAsync().Result;
    var ClientJsonOtp = JsonConvert.DeserializeObject(finalResult);
    string otp = new CacheController().getCacheMethodOne(ClientJsonOtp.ToString());
    return Json(ClientJsonOtp, JsonRequestBehavior.AllowGet);
}


Honey Singh
  • 307
  • 3
  • 10
  • Step through with the debugger, determine which variable is `null` by inspecting them each in turn, and then you'll have your answer. FWIW the second block of code won't compile because `CacheController` doesn't have a parameterless constructor. – ProgrammingLlama Jan 24 '20 at 07:00
  • John, he knows why it is he is getting the exception. He is just checking how to fix if properly. – Athanasios Kataras Jan 24 '20 at 07:06
  • @John thanks for your input but my question was different. . a request to kindly understand the questions before commenting or CLOSING it. – Honey Singh Jan 24 '20 at 08:41
  • I read your question 3 times, and I found your question to be incomplete. Your `CacheController` class and your calling code do not marry up, so it's unclear how you would get that exception since your code shouldn't even compile. Your proposed solution is neither here nor there without us being able to fully understand the situation up to this point. I could have voted to close it as a duplicate, or voted to close it as lacking sufficient information. I chose the more helpful option. Note that coherent questions lend themselves to being understandable. – ProgrammingLlama Jan 24 '20 at 08:54
  • @AthanasiosKataras But it's not clear why Sahil's getting the exception. The question doesn't show us how `CacheController` comes to exist, except for a `new CacheController()` line that won't even compile. To me it seems possible that: 1) it's being injected into the class that the second block of code runs in, but OP has not assigned it to a field and then OP then uses in a different version of the question code, 2) the code is different from the above (is null being passed to the ctor?), or 3) there are two CacheController classes and OP isn't looking at the right one. – ProgrammingLlama Jan 24 '20 at 09:03
  • OP I've reopened your question for you, but I still feel this lacks information. – ProgrammingLlama Jan 24 '20 at 09:07
  • @John hey John, that was a simple exception. Yes, the class was not having parameter less constructor. So doing public IMemoryCache _memoryCache {get;set} would have solved it. The question was that, Should i create new instances of IMemoryCache and add new values to it OR should i create just one instance. I have mentioned it above as well. .[ REPEAT. Should i create new instances of IMemorycahce. If i do so, will it affect the cache. as it may lose the previous cache instance].... anyways Athanasios Kataras is smart enough i guess as he solved the issue with just the liittle info provided. – Honey Singh Jan 24 '20 at 10:31

1 Answers1

3

You need to create one, at least once. Otherwise it will always be null.

You can do that when you call the empty constructor:

public CacheController()
    {
        this._memoryCache = new // whatever memory cache you choose;
    }

You can even better inject it somewhere using dependency injection. The place depends on application type.

But best of all, try to have only once cache. Each time you create one you lose the previous, so you will either try the singleton pattern, or inject using a single instance configuration and let the DI container handle the rest.

An example for the singleton implementation: here

You can access by using:

Cache.Instance.Read(//what)

Here is the cache implementation

using System;
using System.Configuration;
using System.Runtime.Caching;

namespace Client.Project.HelperClasses
{

    /// <summary>
    /// Thread Safe Singleton Cache Class
    /// </summary>
    public sealed class Cache
    {
        private static volatile Cache instance; //  Locks var until assignment is complete for double safety
        private static MemoryCache memoryCache;
        private static object syncRoot = new Object();
        private static string settingMemoryCacheName;
        private static double settingCacheExpirationTimeInMinutes;
        private Cache() { }

        /// <summary>
        /// Singleton Cache Instance
        /// </summary>
        public static Cache Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            InitializeInstance();

                        }
                    }
                }
                return instance;
            }
        }

        private static void InitializeInstance()
        {
            var appSettings = ConfigurationManager.AppSettings;
            settingMemoryCacheName = appSettings["MemoryCacheName"];
            if (settingMemoryCacheName == null)
                throw new Exception("Please enter a name for the cache in app.config, under 'MemoryCacheName'");

            if (! Double.TryParse(appSettings["CacheExpirationTimeInMinutes"], out settingCacheExpirationTimeInMinutes))
                throw new Exception("Please enter how many minutes the cache should be kept in app.config, under 'CacheExpirationTimeInMinutes'");

            instance = new Cache();
            memoryCache = new MemoryCache(settingMemoryCacheName);
        }

        /// <summary>
        /// Writes Key Value Pair to Cache
        /// </summary>
        /// <param name="Key">Key to associate Value with in Cache</param>
        /// <param name="Value">Value to be stored in Cache associated with Key</param>
        public void Write(string Key, object Value)
        {
            memoryCache.Add(Key, Value, DateTimeOffset.Now.AddMinutes(settingCacheExpirationTimeInMinutes));
        }

        /// <summary>
        /// Returns Value stored in Cache
        /// </summary>
        /// <param name="Key"></param>
        /// <returns>Value stored in cache</returns>
        public object Read(string Key)
        {
            return memoryCache.Get(Key);
        }

        /// <summary>
        /// Returns Value stored in Cache, null if non existent
        /// </summary>
        /// <param name="Key"></param>
        /// <returns>Value stored in cache</returns>
        public object TryRead(string Key)
        {
            try
            {
                return memoryCache.Get(Key);
            }
            catch (Exception)
            {
                return null;
            }

        }

    }

}
Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • The above code will create a new instance every time. Yes you were right, I was actually asking for better way of doing it as i was afraid that i may lose my cache. Now i have less idea of DI and singleton pattern. Could you pleas suggest me how should i achieve that. I have two controllers, one to generate a token and other is CacheController. I try to send the token to this cacheController and save it with some value. Yes the token will be valid only for 2 mints. And there will be multiple calls to this cacheController. Now where do i create a global instance of this cachecontroller. – Honey Singh Jan 24 '20 at 07:19
  • I updated with the singleton pattern (an example). For DI, if you are using net core, check this: https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1 – Athanasios Kataras Jan 24 '20 at 07:39
  • I really appreciate your help. its working. . Muchas Gracias – Honey Singh Jan 24 '20 at 08:38