ASP Net Core 3,从数据库设置全局变量并在视图、控制器中使用

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

首先请原谅我的英语不好...

我正在寻找一种在我的所有项目中使用 class 的方法。我向你解释我的需要。因为我不知道该去哪里。 我有一个 Web 项目 asp net core 连接到 sql 服务器。我在里面有一个 public 个页面,其中包含不同的部分(例如:付款、创建、消息、广告、注册...),并且我有一个区域管理员(我的后台)。

我有一个 class :

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

我希望此 class 允许我在我的视图或控制器中设置网站的某些部分是否可访问。 前视图:

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

数据保存在 sql 服务器的 table 中(使用 entity framework),我必须能够从我的管理区域修改它。我希望它是持久的,而不必在每次用户调用页面时都获取它。 我探索了不同的解决方案:

我没有想法,我不知道去哪里......

有点broad/general的问题,但不是很难解决的问题。

  1. 您可以在数据库中创建一个 table,例如AppSettings,带有一个 Name 和一个 Value 字符串列。您可能希望使用常规的 EF Core 代码优先方法执行此操作,创建模型,然后进行迁移。

  2. a) 然后,您需要创建一个组件,它会自动从数据库中读取这些值并将它们插入到应用程序配置中。例如 this seems to be a good implementation candidate.

但是,这引出了一个问题 when/how 您是否希望更新它,因为您提到您不希望在每个请求中都从数据库中读取它。尽管如此,如果您想让它动态配置,您将需要 一些 的重读。除非您愿意table每次修改配置后重新启动您的服务。

  1. b) 另一种选择,而不是上面的配置注入器,是创建一个自定义服务,例如AppSettingsService(或者最好是一个不太通用的名称),您可以在容器中注册为单例范围的服务,并注入您的消费 类。该服务将从数据库中读取值,将它们缓存在内存中,并以一种易于使用的方式公开它们;此外,它还可以公开一种从数据库中刷新值的方法。

如果您需要有关上述任一实施细节的帮助,请告诉我,我可以通过编辑此答案来添加更多细节和代码示例。在不了解更多您的偏好的情况下,无法详细介绍所有内容。

你可以在asp.net核心中使用动态配置来完成这个,我认为这是最好的方法,我推荐你使用这种方法。您可以找到分步指南 here.

Else 您可以从数据库中获取一组值,并在应用程序启动时将它们存储在会话中。 [Source]

首先安装 nuget 包 - Microsoft.AspNetCore.Session

在Startup.cs文件中

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        // Add these 6 lines
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            options.Cookie.IsEssential = true;
        });
        .
        .
        .
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseSession(); //< --- And add this line
        ..............
    }

并且在 C# 中,您可以设置和检索会话存储中的值

using Microsoft.AspNetCore.Http;

public class SomeController : Controller
{    
    public ActionResult Index()
    {   
      HttpContext.Session.SetString("RegistrationEnabled", true ); // Set Session  
      var registrationEnabled = HttpContext.Session.GetString("RegistrationEnabled"); // Get Value of Session
    }    
}

谢谢,根据您的回答,我尝试制作一些有用的东西,但我不知道它是否非常相关。 这是我的设置 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,
}

还有我的服务:

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;
        }
    }

我在 Startup.cs

中添加了这个
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<SettingService>();
}

为了在我看来使用我的设置,我使用这个:

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

进入我的视野:

@setting.GetString("MY_KEY").Result

但这有关系吗?还是好的做法?