ASP.NET Core 2.0 中的应用程序变量

Posted

技术标签:

【中文标题】ASP.NET Core 2.0 中的应用程序变量【英文标题】:Application Variables in ASP.NET Core 2.0 【发布时间】:2018-07-16 19:15:45 【问题描述】:

如何在 ASP.NET Core 2.0 中设置和访问应用程序范围的变量?

详情: 我有一个变量,我们称它为 CompanyName,它驻留在数据库中,几乎用于每个页面。我不想每次需要显示 CompanyName 时都访问数据库。 100 年前,我会设置 Application["CompanyName']=CompanyName,但我知道这不是在 .NET Core 中做事的方式。有什么替代方案?

【问题讨论】:

您的应用程序中是否有其他会话上下文,例如用户/租户/授权声明或此变量属于或可能同时检索的其他配置文件信息。在这种情况下,您可以调用它。或者使用某种带有缓存的数据调用/检索? 【参考方案1】:

在过去的 100 年中取得了很大进展。前段时间,我相信在 ASP.NET 1.0 中,ASP classic 中的 Application 对象被 caching 所取代(尽管 Application 对象被保留是为了向后兼容 ASP classic)。

AspNetCore 具有replaced the caching mechanism of ASP.NET 并使其对 DI 友好,但它仍然与 ASP.NET 中的事物状态非常相似。主要区别在于您现在需要注入它而不是使用静态 HttpContext.Current.Cache 属性。

启动时注册缓存...

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

public class Startup

    public void ConfigureServices(IServiceCollection services)
    
        services.AddMemoryCache();
        services.AddMvc();
    

    public void Configure(IApplicationBuilder app)
    
        app.UseMvcWithDefaultRoute();
    

你可以像...一样注入它

public class HomeController : Controller

    private IMemoryCache _cache;

    public HomeController(IMemoryCache memoryCache)
    
        _cache = memoryCache;
    

    public IActionResult Index()
    
        string companyName = _cache[CacheKeys.CompanyName] as string;

        return View();
    

然后,要使其在应用程序范围内工作,您可以使用 filtermiddleware 并结合某种缓存刷新模式:

    尝试从缓存中获取值 如果尝试失败 从数据库中查找数据 重新填充缓存 返回值

public string GetCompanyName()

    string result;

    // Look for cache key.
    if (!_cache.TryGetValue(CacheKeys.CompanyName, out result))
    
        // Key not in cache, so get data.
        result = // Lookup data from db

        // Set cache options.
        var cacheEntryOptions = new MemoryCacheEntryOptions()
            // Keep in cache for this time, reset time if accessed.
            .SetSlidingExpiration(TimeSpan.FromMinutes(60));

        // Save data in cache.
        _cache.Set(CacheKeys.CompanyName, result, cacheEntryOptions);
    

    return result;

当然,您可以清理它并创建一个具有强类型属性的服务,作为注入到控制器中的缓存的包装器,但这是一般的想法。

注意还有一个distributed cache,以防您想在网络服务器之间共享数据。

您可以选择使用静态方法或静态注册的类实例,但请注意,如果托管在 IIS 上,静态将每次应用程序池回收时超出范围。因此,要实现这一点,您需要确保使用类似的刷新模式重新填充数据。

主要区别在于缓存有超时设置,可用于优化数据应在缓存中存储多长时间(硬时间限制或滑动到期)。

【讨论】:

我希望避免将其注入每个控制器。也许将其注入到视图组件中? 这也行。控制器是注入依赖项的最常见位置(这就是我选择该示例的原因),但它不是唯一可以注入的位置。正如我在回答中提到的,do 改进了这个解决方案——围绕缓存创建自己的包装器,该包装器随处注入,并将缓存元素作为强类型属性公开。 我让它在视图组件中工作,此外,我在编辑组织信息时从缓存中删除了该项目。感谢您的帮助。 我喜欢这个解决方案并想使用它。我的情况的不同之处在于我想在应用程序级别缓存项目列表,并且我希望能够从任何用户会话预先或附加到列表中,并让所有用户在他们的下一个请求中都可以使用这些新信息。我应该每次都获取/设置整个列表吗?我应该在追加/前置之前锁定列表吗?【参考方案2】:

您可以创建一个名为 ApplicationWideSettings 的单例类。为该类提供公共属性。一次性初始化您需要的所有值,然后通过以下方式访问您的类的唯一实例来使用它们:

ApplicationWideSettings.Instance.PropertyName;

只要确保在您想要访问 ApplicationWideSettings 类的命名空间时引用它即可。

我更喜欢这个而不是全局/静态设置,因为你有一个类来保存你所有的全局可用数据。

如果您不确定什么是 Singleton,我可以建议您查看 Jon Skeet 的这篇文章:

C# In Depth: Implementing the Singleton Pattern in C#

【讨论】:

以上是关于ASP.NET Core 2.0 中的应用程序变量的主要内容,如果未能解决你的问题,请参考以下文章

ApplicationUser在Asp.Net Core 2.0中的ActionFilter中?

ASP.NET CORE 2.0 中的 FromUri

ASP.NET Core 2.0中的HttpContext

ASP.Net Core项目在Mac上使用Entity Framework Core 2.0进行迁移可能会遇到的一个问题.

asp.net core 2.0 中的 WCF - 无法为具有权限的 SSL/TLS 安全通道建立信任关系

如何将 UserManager 注入 ASP.NET Core 2.0 中的另一个服务