【问题标题】:How can I make a session variable available to all controllers without accessing HttpContext in each controller?如何在不访问每个控制器中的 HttpContext 的情况下使所有控制器都可以使用会话变量?
【发布时间】:2018-12-19 15:25:34
【问题描述】:

我正在尝试通过使用HttpContext.Session.GetInt32("BranchId").Value 使int 变量BranchId 在我的应用程序中可用。

根据我自己的尝试以及对this question 的回答,这种方法行不通:

基本控制器类:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Vaktliste.Controllers
{
    public class MyBaseControllerClass : Controller
    {
        public readonly int branchId;

        public MyBaseControllerClass()
        {
            var s = HttpContext.Session; // <-- This causes a NULL exception
            // SET THE VARIABLE HERE:
            BranchId = s.GetInt32("BranchId") != null
                ? s.GetInt32("BranchId").Value
                : 0;
        }
    }
}

应用程序中另一个控制器的示例:

namespace Vaktliste.Controllers
{
    public class BranchesController : MyBaseControllerClass
    {
        private readonly VaktlisteContext db;

        public BranchesController(VaktlisteContext context)
        {
            db = context;
        }

        public async Task<IActionResult> Details(int? id)
        {
            // USE THE VARIABLE HERE:
            if (id == null) id = BranchId;

            if (id == null) return NotFound();

            var branch = await db.Branches
                .Where(m => m.Id == id)
                .FirstOrDefaultAsync();

            if (branch == null) return NotFound();

            HttpContext.Session.SetInt32("BranchId", branch.Id);

            return View(branch);
        }
    }
}

我当然可以在每个控制器中使用GetInt32("BranchId"),但我想让它保持干燥(不要重复自己)。怎么办?

【问题讨论】:

  • 您可以在基类中将分支 id 设为 Lazy,然后在请求期间(而非构造函数)可用。

标签: c# session asp.net-core-mvc httpcontext


【解决方案1】:

也许您可以通过属性来实现这一点。创建基本控制器时,httpcontext.session 为空。如果你使用一个属性并且只在你的路由中访问它,那么会话应该是可用的。

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Vaktliste.Controllers
{
    public class MyBaseControllerClass : Controller
    {
        public readonly int branchId;
        protected int BranchId { 
            get { HttpContext.Session?.GetInt32("BranchId")?.Value ?? 0; }
            set { HttpContext.Session.SetInt32("BranchId", value); }
        }

        public MyBaseControllerClass()
        {

        }
    }
}

然后只需访问该属性即可获取值

namespace Vaktliste.Controllers
{
    public class BranchesController : MyBaseControllerClass
    {
        private readonly VaktlisteContext db;

        public BranchesController(VaktlisteContext context)
        {
            db = context;
        }

        public async Task<IActionResult> Details(int? id)
        {
            // USE THE VARIABLE HERE:
            id = id ?? BranchId;

            if (id == null) return NotFound();

            var branch = await db.Branches
                .Where(m => m.Id == id)
                .FirstOrDefaultAsync();

            if (branch == null) return NotFound();

            BranchId = branch.Id;

            return View(branch);
        }
    }
}

【讨论】:

    【解决方案2】:

    我会创建一个protected 变量并使用它来包装您的访问器:

    protected int? BranchId
    {
       get { return (HttpContext.Session["BranchId] as int?); }
       set { HttpContext.Session.SetInt32("BranchId", value);
    }
    

    然后将您的倒数第二行更新为:

    this.BranchId = branch.Id;

    当然,所有子类控制器都只访问受保护的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2020-07-03
      • 1970-01-01
      • 2017-09-22
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      相关资源
      最近更新 更多