繁体   English   中英

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

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

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

我正在寻找一种在我的所有项目中使用 class 的方法。 我向你解释我的需要。 因为我不知道 go 在哪里。 我有一个 web 项目 asp 网络核心连接到 sql 服务器。 在里面我有一个不同部分的公共页面(例如:支付,创建,消息,广告,注册......),我有一个区域管理员(我的后台)。

我有一个 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 服务器(带有实体框架)的表中,我必须能够从我的管理区域修改它。 我希望它是持久的,而不必在每次用户调用页面时都获取它。 我探索了不同的解决方案:

  • appSetting:但我认为我无法从我的管理界面进行编辑?
  • 资源文件:但我不认为我可以直接编辑它?
  • Singleton?
  • Azure?

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

这是一个广泛/普遍的问题,但不是一个难以解决的问题。

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

  2. a) 然后,您需要创建一个组件,该组件将自动从数据库中读取这些值并将它们插入到应用程序配置中。 例如,这似乎是一个很好的实现候选者

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

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

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

您可以在 asp.net 内核中使用动态配置来完成此操作,我认为这是最好的方法,我建议您使用这种方法。 您可以在此处找到分步指南。

否则,您可以在应用程序启动时从数据库中获取您的一组值并将它们存储在 session 中。 [资源]

首先安装 nuget package - 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# 中,您可以设置和检索 Session 存储中的值

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

但这相关吗? 还是好的做法?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM