ASP.NET Web API:如何跨请求创建持久集合?

fdm*_*ion 4 c# asp.net-web-api

我有一个 Web API,它为 Angular.JS Web 应用程序提供后端。后端 API 需要跟踪用户活动的状态。(例如:需要记录用户上次从 API 中检索到的内容 ID)

对 API 的大多数访问都通过用户名/密码进行身份验证。对于这些实例,我可以将用户状态存储在我们的数据库中。

但是,我们确实需要允许“访客”访问该服务。对于来宾,状态确实需要跟踪,但不应长期保持(例如会话级跟踪)。我真的不想在我们的用户表中生成“伪用户”,只是为了存储来宾用户的状态,不需要长时间维护。

我的计划是生成一个随机值并将其作为 cookie 存储在客户端中。(仅适用于客人 - 我们对经过身份验证的用户使用不记名身份验证。)然后我将使用随机值作为密钥将任何必要的状态存储在内存对象中,例如字典。然后我可以定期使字典中的项目过期。如果 Web API 重新启动,这些数据丢失是完全可以接受的,甚至可以接受字典重置,比如每天的某个时间。

我不知道如何在 WebAPI 中做的是创建字典对象,以便它在 Web API 调用中保持不变。我基本上需要一个单例字典对象,只要服务器运行 Web API,它就会保持其内容(除非计划清除或程序化刷新)

我的想法是每次进行 API 调用时将字典转储到磁盘,然后在需要时将其读回,但这不允许多个同时进行的请求。我现在能想到的唯一方法是添加另一个数据库表(guest_state 或其他东西)并复制用户表,然后设置某种手动方法来定期清理来宾表中的数据。

总结:我需要的是

  • 一种将一些数据持久存储在 Web API 后端中而不必转到数据库的方法
  • 最好将此数据存储在 Dictionary 对象中,以便我可以使用随机生成的会话 ID 作为键,并使用一个对象来存储状态
  • 数据可以在设定的时间段后或定期清除(不要频繁,可能至少有 6 小时的持久性)

fdm*_*ion 5

我想出了一个使用单例模式的解决方案:

public static class Services 
{
    private static Dictionary<string, string> cache;

    private static object cacheLock = new object();
    public static Dictionary<string,string> AppCache
    {
        get
        {
            lock (cacheLock)
            {
                if (cache == null)
                {
                    cache = new Dictionary<string, string>();
                }
                return cache;
            }
        }
    }
}

public class testController()
{
    [HttpGet]
    public HttpResponseMessage persist()
    {
        HttpResponseMessage hrm = Request.CreateResponse();
        hrm.StatusCode = HttpStatusCode.OK;

        Services.AppCache.Add(Guid.NewGuid().ToString(), DateTime.Now.ToString());

        string resp = "";

        foreach (string s in Services.AppCache.Keys)
        {
            resp += String.Format("{0}\t{1}\n", s, Services.AppCache[s]);
        }
        resp += String.Format("{0} records.", Services.AppCache.Keys.Count);

        hrm.Content = new StringContent(resp, System.Text.Encoding.ASCII, "text/plain");
        return hrm;
    }        
}
Run Code Online (Sandbox Code Playgroud)

Services.AppCache对象似乎成功地保留了数据,直到空闲超时到期或应用程序池回收为止。幸运的是,我可以在 IIS 中控制所有这些,所以我将我的应用程序移到了它自己的 AppPool,并根据我对刷新的数据是否满意,适当地设置了空闲超时和回收。

遗憾的是,如果您无法控制 IIS(或无法要求管理员为您设置设置),如果默认到期时间对您来说太早,这可能不起作用......此时使用类似LocalDB 文件甚至平面 JSON 文件可能更有用。

  • 两个重点:您需要使用“ConcurrentDictionary”而不是“字典”。字典不是线程安全的,一旦多个用户开始使用您的应用程序,您就会遇到异常(请记住,请求是并发处理的)。其次,一个建议,`System.Web.Caching.Cache` 本质上正是你要找的,它也为你提供了过期逻辑:https://msdn.microsoft.com/en-us/library/ system.web.caching.cache(v=vs.110).aspx 在 ASP.net 应用程序中,您可以在 `HttpContext.Cache` 中使用缓存的单例实例 (3认同)