1

我正在使用 ASP.NET Core 和 Identity 3。

当我登录时,我阅读了当前选择用户的 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;
        {

我想知道如果会话到期会发生什么。

  1. 考虑到我访问了 my_Layout.cshtml中的值,如果它变为 null 并在呈现新页面之前立即从数据库中加载它,无论如何都会捕获它。

  2. 由于我使用 Identity 3,Claims 可能是更好的选择吗?我以前没用过。我上面的示例的代码是什么

  3. 另一个更适合我的方案的选择?

4

2 回答 2

1

我没有在每次加载 cshtml 时都查询数据库,而是将模板放在 Session 变量中,并在 Layout.cshtml 中根据模板呈现不同的 css

如果访问数据库是您唯一关心的问题,并且您已经抽象了存储库(或用户存储,如果您将其存储在身份类型上),则可以使用装饰器模式来实现本地缓存。

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 Core DI 系统中没有对装饰器的内置支持。您必须使用第 3 方 IoC 容器(Autofac、StructureMap 等)。

你当然可以这样注册

    services.AddScoped<IUserRepository>(container => {
        return new CachedUserRepository(container.GetService<UserRepository>(), container.GetServices<IMemoryCache>());
    });

但这有点麻烦。否则将其存储在一个长期存在的 cookie 中,它的优点是当用户未登录时主题仍然处于活动状态,并且您可以在用户登录时设置 cookie。

于 2016-02-22T21:35:19.307 回答
0

如果您愿意,您当然可以将主题存储在用户的身份中,但是每当您更新主题时,您都必须让用户退出......

你会做这样的事情:

userManager.AddClaimAsync(user, new Claim("Template", id+""));
signInManager.SignInAsync(user);
于 2016-02-22T20:06:26.627 回答