【问题标题】:Strongly typed TempData in CoreCore 中的强类型 TempData
【发布时间】:2022-01-18 05:00:31
【问题描述】:

使用 Web 表单,我可以为强类型会话创建包装器:

public class MySession
{
    public static MySession Current
    {
        get
        {
            MySession session = (MySession)HttpContext.Current.Session["__MySession__"];

            if (session == null)
            {
                session = new MySession();
                HttpContext.Current.Session["__MySession__"] = session;
            }

            return session;
        }
    }

    public string TestString { get; set; }
}

我正在尝试对 Core 中的 TempData 做同样的事情:

public class MySession
{
    public static MySession Current
    {
        get
        {
            var _sessionId = "_MyTempData_";

            var httpContext = new HttpContextAccessor().HttpContext;
            var tempDataFactory = httpContext.RequestServices.GetRequiredService<ITempDataDictionaryFactory>();
            var tempData = tempDataFactory.GetTempData(httpContext);

            var val = tempData.Peek(_sessionId) as string;

            MySession mySession;
            if (string.IsNullOrWhiteSpace(val))
            {
                mySession = new();
                tempData[_sessionId] = JsonConvert.SerializeObject(mySession);
                tempData.Save();
            }
            else
                mySession = JsonConvert.DeserializeObject<MySession>(val);

            return mySession;
        }
    }

    public string TestString { get; set; }

}

但我的 TestString 值始终为空:

MySession.Current.TestString = "Test";
var x = MySession.Current.TestString //always null

是因为我能够存储实际的 MySession 对象,所以它被引用了,还是什么?

【问题讨论】:

  • 我会说你最好让你的MySession成为一个实例类,让ctor接受IHttpContextAccessor并将MySession注册为一个作用域服务。
  • new HttpContextAccessor() 你不应该这样做。 HttpContextAccessor() 的新实例不会为您提供控制器使用的相同 httpContext。此外,每次调用此 Current 属性都会创建一个新的 HttpContextAccessor ,这将导致一切都是新的。甚至临时数据字典。这就是为什么即使在您先设置后也无法取回该值

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


【解决方案1】:

请注意,在 .net core 中使用 HttpContext 类来存储数据状态并不是一个好的做法。

有指定的类来执行操作,更简洁,更高效。在您的情况下,为了存储会话状态,您可以使用 Isession 接口。

它实现了传统的GetSet方法,用于string和int(int32,int16)。

我附上的link 应该涵盖用例,并为您提供有关如何使用它的提示。

【讨论】:

    【解决方案2】:

    如何使用非静态类并将数据与逻辑分离?

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.ViewFeatures;
    using Newtonsoft.Json;
    
    namespace Test
    {
        // Add to Startup.cs
        // services.AddScoped<SessionService>();
    
        public class SessionService
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
            private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;
            private readonly string _sessionId = "_MyTempData_";
            
            public SessionService(IHttpContextAccessor httpContextAccessor, ITempDataDictionaryFactory tempDataDictionaryFactory)
            {
                _httpContextAccessor = httpContextAccessor;
                _tempDataDictionaryFactory = tempDataDictionaryFactory;
            }
    
            public SessionData Current
            {
                get
                {
                    var httpContext = _httpContextAccessor.HttpContext;
                    var tempData = _tempDataDictionaryFactory.GetTempData(httpContext);
    
                    var val = tempData.Peek(_sessionId) as string;
    
                    SessionData mySession;
                    if (string.IsNullOrWhiteSpace(val))
                    {
                        mySession = new();
                        tempData[_sessionId] = JsonConvert.SerializeObject(mySession);
                        tempData.Save();
                    }
                    else
                        mySession = JsonConvert.DeserializeObject<SessionData>(val);
    
                    return mySession;
                }
                
            }
        }
    }
    

    数据的单独类,

    namespace Test
    {
         public class SessionData
         {
            public string TestString { get; set; }
         }
    }
    

    在 ASP.NET Core 网页中的使用:

    namespace Test
    {
        [Authorize]
        public class HomeController : Controller
        {
            private readonly SessionService _sessionService;
            private SessionData SessionData => _sessionService.Current;
    
            public HomeController(SessionService sessionService)
            {
                _sessionService = sessionService;
            }
            
            [HttpGet]
            public IActionResult Index()
            {
                var hi = SessionData.TestString;
                
                return View(hi);
            }
        }
    }
        
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-12
      • 2018-02-04
      • 2019-02-10
      • 1970-01-01
      • 1970-01-01
      • 2019-02-03
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多