【问题标题】:Using global variable in ASP.NET Core controller在 ASP.NET Core 控制器中使用全局变量
【发布时间】:2017-09-30 01:12:38
【问题描述】:

问题很简单,但不知道怎么用。

例如有一个控制器

public class MainController : Controller
{
    private int a;

    public IActionResult Index(bool set = true)
    {
        if (set) a = 10;

        return View(a)
    }
}

如果我第一次进入索引页面,我设置a = 10。然后我再次进入索引页面(例如刷新索引页面或在索引页面中分页,即移入同一页面)实际上,我进入了索引首次访问后带有 url 的页面:~Index?set=False

那么a 的值为 0(int 变量的默认值)。我不知道控制器页面(控制器类)在我生成时总是被初始化,即使我移动到同一页面也是如此。

所以,我想使用像全局变量这样的变量,而不是使用会话。

有什么办法吗?

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc


    【解决方案1】:

    听起来您希望在请求之间保留一个变量。

    每位用户

    如果您希望存储一个持续存在但仅对当前用户可见的变量,请使用session state

    public int? A
    {
        get 
        {
            return HttpContext.Current.Session["A"] as int?;
        }
        set
        {
            HttpContext.Current.Session["A"] = value;
        }
    }
    

    请注意,我们使用int? 而不是int 来处理尚未设置会话变量的情况。如果你喜欢默认为 0,你可以简单地使用the coalesce operator, ??

    真正的全球化

    如果您希望以一种对所有用户只有一个副本的方式保存变量,您可以将其存储在静态变量或应用程序状态变量中。

    所以

    static volatile public int a;
    

    或者

    public int? A
    {
        get 
        {
            return HttpContext.Current.Application["A"] as int?;
        }
        set
        {
            HttpContext.Current.Application["A"] = value;
        }
    }
    

    显然,在用户之间共享的变量可以随时更改(由于其他线程中的活动),因此您应该小心处理它们的方式。对于int 或更小的变量,处理器将执行原子读写,但对于大于int 的变量,您可能需要使用Interlockedlock 来控制访问。

    您无需担心会话变量的线程同步;框架会为您处理。

    注意:以上只是帮助您找到正确 API 的示例。它不一定展示出最好的模式——通过静态方法Current 访问HttpContext 被认为是错误的形式,因为它使得无法模拟上下文。请参阅this article 了解通过 DI 将其公开给您的代码的方法。

    【讨论】:

    • 100% 同意@Tseng​​span>
    • 现在阅读。有人可以详细说明@Tseng 的问题是什么吗?他所说的反模式到底是什么?他对所提供的两种解决方案(按用户和真正全球)是否有问题?
    • 在哪里存储变量或使用什么具体对象没有分歧 (HttpContext)。但是有other ways 获取HttpContext 的当前实例而不是使用Current 方法。见this question
    猜你喜欢
    • 2019-12-13
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    相关资源
    最近更新 更多