2016-09-18 47 views
2

我有一个Web API提供一个Angular.JS Web应用程序的后端。后端API需要跟踪用户活动的状态。 (例如:需要注意用户最近从API中检索的内容ID)ASP.NET Web API:如何跨请求创建持久集合?

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

但是,我们确实需要允许“访客”访问该服务。对于客人而言,该州确实需要进行跟踪,但不应长期持续(例如会话级别跟踪)。我真的很希望不必在我们的用户表中生成“伪用户”来存储访客用户的状态,这不需要在很长一段时间内维护。

我的计划是生成一个随机值并将其作为cookie存储在客户端中。 (仅适用于客人 - 我们使用承认身份验证用户身份)。然后,我会使用随机值作为关键字在内存对象(如Dictionary)中存储任何必需的状态。我可以定期从字典中删除项目。如果Web API重新启动,那么这些数据就会丢失是完全可以接受的,甚至在特定时间每天都可以重置字典甚至是可以接受的。

我不知道如何做的WebAPI是创建字典对象,以便它将持续跨Web API调用。我基本上需要一个singleton字典对象,只要服务器运行Web API,它就会保持它的内容(禁止计划清除或程序性冲洗)

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

摘要:我需要的是

  • 持久地存储在Web API后端一些数据的方式,而不必去开了一个数据库
  • 最好存储在Dictionary对象这个数据,所以我可以使用随机生成的会话ID作为密钥,并存储对象以存储状态
  • 数据可以在设定的时间段内或定期清除(不是也可以是,也可以是最少的6小时持久性)

回答

1

我想出使用Singleton模式的解决方案:

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; 
    }   
} 

看来Services.AppCache对象成功地保存到数据直到或者空闲超时过期或应用程序池回收。幸运的是,我可以控制IIS中的所有内容,所以我将我的应用程序移动到它自己的AppPool中,并根据何时适合正在刷新的数据设置空闲超时和回收。

不幸的是,如果您无法控制IIS(或者无法要求管理员为您设置设置),那么如果默认过期对您来说太快,这可能不起作用......在那时使用类似LocalDB文件或甚至平坦的JSON文件可能会更有用。

+1

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