Search code examples
c#entity-frameworkasp.net-coreconfigurationglobal-variables

ASP Net Core 3, set global variable from database and use in view, controllers


First of all excuse me for my bad english ...

I'm looking for a way to use a class in all my project. I explain my need to you. Because I don't know where to go. I'have a web project asp net core connected to sql server. Inside i have a public pages with different section (ex: payment, create, message, ads, register...), and i have a area admin (back office for me).

I have a class :

public class Section
{
   public bool RegistrationEnabled { get; set; }
   public bool PaymentEnabled { get; set; }
   public bool PublicationEnabled { get; set; }
   public bool MessageEnabled { get; set; }
}

I want this class to allow me to make certain part of the site accessible or not in my views or in my controllers. Ex in view :

@if (Section.RegistrationEnabled)
{ 
   // Display form register..
}

The data is saved in a table in sql server (with entity framework), and I must be able to modify it from my admin area. I would like it to be persistent without having to fetch it each time a page is called by a user. I have explored different solution:

  • appSetting: but I can't edit from my admin interface I think?
  • Resource file: But I don't think I can edit it directly?
  • Singleton?
  • Azure ?

I'm out of ideas and I don't know where to go ...


Solution

  • Thanks, from your answers I tried to produce something that works, but I don't know if it's very relevant. This is my setting class :

    [Table("SETTING")]
    public class Setting : BaseObject
    {
       [Key]
       [StringLength(50)]
       public string Key { get; set; }
       [StringLength(50)]
       public string Value { get; set; }
       public e_SettingType Type { get; set; }
    }
    public enum e_SettingType
    {
       UNDEFINED,
       BOOL,
       BYTE,
       CHAR,
       DECIMAL,
       DOUBLE,
       FLOAT,
       INT,
       STRING,
    }
    

    And my service :

    public class SettingService
        {
            private const string CACHE_KEY = "CurrentSetting";
            private readonly IMemoryCache _cache;
            private readonly IBaseRepository<Setting> _setting;
            public SettingService(IMemoryCache cache, IBaseRepository<Setting> setting)
            {
                _cache = cache;
                _setting = setting;
            }
            public async Task<bool> GetBool(string key)
            {
                var settings = await GetFromCache();
                if (settings != null && settings.Any(x => x.Key.Equals(key)))
                    return bool.Parse(settings.First(x => x.Key.Equals(key)).Value);
                else
                    return default;
            }
            public async Task<string> GetString(string key)
            {
                var settings = await GetFromCache();
                if (settings != null && settings.Any(x => x.Key.Equals(key)))
                    return settings.First(x => x.Key.Equals(key)).Value;
                else
                    return default;
            }
            private async Task<List<Setting>> GetFromCache()
            {
                if (!_cache.TryGetValue(CACHE_KEY, out List<Setting> data))
                {
                    var models = await _setting.FindAll();
                    data = models.ToList();
    
                    var cacheOptions = new MemoryCacheEntryOptions()
                        .SetAbsoluteExpiration(TimeSpan.FromMinutes(30));
    
                    _cache.Set(CACHE_KEY, data, cacheOptions);
                    return data;
                }
                else
                    return data;
            }
        }
    

    I've add this in Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<SettingService>();
    }
    

    And for consume my setting in my view, i use this :

    @inject MyProject.Service.SettingService setting //top of view
    

    Get in my view :

    @setting.GetString("MY_KEY").Result
    

    But is this relevant? Or good practice?