如何访问 _Layout 中的会话而不用担心它已过期
How to access a session in in the _Layout without worrying it has expired
我正在使用 ASP.NET Core & Identity 3。
当我登录时,我读取了当前 select 用户的 UI 模板,并在我的 _Layout.cshml
文件中加载了基于该模板的 css
。
用户可以更改他的主题,我通过控制器将其存储在会话变量中
public IActionResult ChangeTheme(int id, string returnUrl)
{
HttpContext.Session.SetInt32("Template", (id));
return Redirect(returnUrl);
}
我没有在每次 cshtml
加载时查询数据库,而是将模板放在 Session 变量中,在我的 Layout.cshtml
中,我根据模板呈现不同的 css
switch (template)
{
case (int)TemplateEnum.Template2:
<text>
<link rel="stylesheet" href="~/css/template1.css" />
</text>
break;
case (int)TemplateEnum.Template2:
<text>
<link rel="stylesheet" href="~/css/template2.css" />
</text>
break;
{
我想知道如果会话过期会发生什么。
考虑到我访问了 _Layout.cshtml
中的值,如果它变为 null 是否仍然可以捕获它并在呈现新页面之前立即从数据库加载它。
因为我使用身份 3,Claims 是否是更好的选择?我以前没用过。我上面的例子的代码是什么
另一个更适合我的方案的选项?
如果您愿意,您当然可以将主题存储在用户的身份中,但是无论何时更新主题,您都必须让用户退出...
你会这样做:
userManager.AddClaimAsync(user, new Claim("Template", id+""));
signInManager.SignInAsync(user);
Instead of querying the database with every cshtml load I put the Template in a Session variable and in my Layout.cshtml I render a different css depending on the template
如果访问数据库是您唯一关心的问题并且您已经抽象了您的存储库(或用户存储,如果您将其存储在身份类型上),您可以使用装饰器模式来实现本地缓存。
public interface IUserRepository
{
string GetUserTheme(int userId);
void SetUserTheme(int userId, string theme);
}
public class CachedUserRepository : IUserRepository
{
private readonly IMemoryCache cache;
private readonly IUserRepository userRepository;
// Cache Expire duration
private static TimeSpan CacheDuration = TimeSpan.FromMinutes(5);
public CachedUserRepository(IUserRepository userRepository, IMemoryCache memoryCache)
{
if (userRepository == null)
throw new ArgumentNullException(nameof(userRepository));
if (memoryCache == null)
throw new ArgumentNullException(nameof(memoryCache));
this.userRepository = userRepository;
this.cache = memoryCache;
}
public string GetUserTheme(int userId)
{
string theme;
// adding a prefix to make the key unique
if (cache.TryGetValue($"usertheme-{userId}", out theme))
{
// found in cache
return theme;
};
// fetch from database
theme = userRepository.GetUserTheme(userId);
// put it into the cache, expires in 5 minutes
cache.Set($"usertheme-{userId}", theme, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = CacheDuration });
return theme;
}
public void SetUserTheme(int userId, string theme)
{
// persist it
userRepository.SetUserTheme(userId, theme);
// put it into the cache, expires in 5 minutes
cache.Set($"usertheme-{userId}", theme, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = CacheDuration });
}
}
要注意的是,在默认 ASP.NET 核心 DI 系统中没有对装饰器的内置支持。您必须使用第 3 方 IoC 容器(Autofac、StructureMap 等)。
当然可以这样注册
services.AddScoped<IUserRepository>(container => {
return new CachedUserRepository(container.GetService<UserRepository>(), container.GetServices<IMemoryCache>());
});
但这有点麻烦。否则将其存储在长期存在的 cookie 中,它的优点是当用户未登录时主题仍然处于活动状态,并且您可以在用户登录时设置 cookie。
我正在使用 ASP.NET Core & Identity 3。
当我登录时,我读取了当前 select 用户的 UI 模板,并在我的 _Layout.cshml
文件中加载了基于该模板的 css
。
用户可以更改他的主题,我通过控制器将其存储在会话变量中
public IActionResult ChangeTheme(int id, string returnUrl)
{
HttpContext.Session.SetInt32("Template", (id));
return Redirect(returnUrl);
}
我没有在每次 cshtml
加载时查询数据库,而是将模板放在 Session 变量中,在我的 Layout.cshtml
中,我根据模板呈现不同的 css
switch (template)
{
case (int)TemplateEnum.Template2:
<text>
<link rel="stylesheet" href="~/css/template1.css" />
</text>
break;
case (int)TemplateEnum.Template2:
<text>
<link rel="stylesheet" href="~/css/template2.css" />
</text>
break;
{
我想知道如果会话过期会发生什么。
考虑到我访问了
_Layout.cshtml
中的值,如果它变为 null 是否仍然可以捕获它并在呈现新页面之前立即从数据库加载它。因为我使用身份 3,Claims 是否是更好的选择?我以前没用过。我上面的例子的代码是什么
另一个更适合我的方案的选项?
如果您愿意,您当然可以将主题存储在用户的身份中,但是无论何时更新主题,您都必须让用户退出...
你会这样做:
userManager.AddClaimAsync(user, new Claim("Template", id+""));
signInManager.SignInAsync(user);
Instead of querying the database with every cshtml load I put the Template in a Session variable and in my Layout.cshtml I render a different css depending on the template
如果访问数据库是您唯一关心的问题并且您已经抽象了您的存储库(或用户存储,如果您将其存储在身份类型上),您可以使用装饰器模式来实现本地缓存。
public interface IUserRepository
{
string GetUserTheme(int userId);
void SetUserTheme(int userId, string theme);
}
public class CachedUserRepository : IUserRepository
{
private readonly IMemoryCache cache;
private readonly IUserRepository userRepository;
// Cache Expire duration
private static TimeSpan CacheDuration = TimeSpan.FromMinutes(5);
public CachedUserRepository(IUserRepository userRepository, IMemoryCache memoryCache)
{
if (userRepository == null)
throw new ArgumentNullException(nameof(userRepository));
if (memoryCache == null)
throw new ArgumentNullException(nameof(memoryCache));
this.userRepository = userRepository;
this.cache = memoryCache;
}
public string GetUserTheme(int userId)
{
string theme;
// adding a prefix to make the key unique
if (cache.TryGetValue($"usertheme-{userId}", out theme))
{
// found in cache
return theme;
};
// fetch from database
theme = userRepository.GetUserTheme(userId);
// put it into the cache, expires in 5 minutes
cache.Set($"usertheme-{userId}", theme, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = CacheDuration });
return theme;
}
public void SetUserTheme(int userId, string theme)
{
// persist it
userRepository.SetUserTheme(userId, theme);
// put it into the cache, expires in 5 minutes
cache.Set($"usertheme-{userId}", theme, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = CacheDuration });
}
}
要注意的是,在默认 ASP.NET 核心 DI 系统中没有对装饰器的内置支持。您必须使用第 3 方 IoC 容器(Autofac、StructureMap 等)。
当然可以这样注册
services.AddScoped<IUserRepository>(container => {
return new CachedUserRepository(container.GetService<UserRepository>(), container.GetServices<IMemoryCache>());
});
但这有点麻烦。否则将其存储在长期存在的 cookie 中,它的优点是当用户未登录时主题仍然处于活动状态,并且您可以在用户登录时设置 cookie。