简体   繁体   English

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

[英]ASP.NET Web API: How to create a persistent collection across requests?

I have a Web API providing a backend to an Angular.JS web application. 我有一个Web API,为Angular.JS Web应用程序提供后端。 The backend API needs to track the state of user activities. 后端API需要跟踪用户活动的状态。 (Example: it needs to note which content ID a user last retrieved from the API) (示例:需要注意用户上次从API检索的内容ID)

Most access to the API is authenticated via username/password. 大多数API访问都通过用户名/密码进行身份验证。 For these instances, it works fine for me to store the user state in our database. 对于这些实例,我可以将用户状态存储在我们的数据库中。

However, we do need to allow "guest" access to the service. 但是,我们确实需要允许“访客”访问该服务。 For guests, the state does need to be tracked but should not be persisted long-term (eg session-level tracking). 对于客人,需要跟踪州,但不应长期持久(例如会话级跟踪)。 I'd really like to not have to generate "pseudo users" in our user table just to store the state for guest users, which does not need to be maintained for a significant period of time. 我真的不想在我们的用户表中生成“伪用户”只是为了存储访客用户的状态,这不需要在相当长的一段时间内维护。

My plan is to generate a random value and store it in the client as a cookie. 我的计划是生成一个随机值并将其作为cookie存储在客户端中。 (for guests only - we use bearer authentication for authenticated users.) I would then store whatever state is necessary in an in-memory object, such as a Dictionary, using the random value as a key. (仅限访客 - 我们对经过身份验证的用户使用承载身份验证。)然后,我将使用随机值作为密钥存储内存对象(如Dictionary)中所需的任何状态。 I could then expire items off the dictionary periodically. 然后我可以定期将字典中的项目过期。 It is perfectly acceptable for this data to be lost if the Web API is ever relaunched, and it would even be acceptable for the dictionary to be reset say, every day at a certain time. 如果重新启动Web API,则完全可以接受这些数据丢失,并且甚至可以接受字典重置,例如,每天在特定时间重置。

What I don't know how to do in WebAPI is create the dictionary object, so that it will persist across Web API calls. 我不知道如何在WebAPI中创建字典对象,以便它将在Web API调用中持久化。 I basically need a singleton dictionary object that will maintain its contents for as long as the server is running the Web API (barring a scheduled clearing or programmatic flushing) 我基本上需要一个单例字典对象,只要服务器运行Web API,就会维护其内容(除非计划清算或程序化刷新)

I had the idea of dumping the Dictionary off to disk every time an API call is made, and then reading it back in when it's needed, but this does not allow for multiple simultaneous in-flight requests. 我有想法在每次进行API调用时将字典转储到磁盘,然后在需要时将其读回,但这不允许多个同时进行的飞行请求。 The only method I can think of right now is to add another database table (guest_state or something) and replicate the users table, and then setup some sort of manual method to regularly clean out the data in the guest table. 我现在能想到的唯一方法是添加另一个数据库表(guest_state或其他)并复制users表,然后设置某种手动方法来定期清理guest表中的数据。

Summary: what I need is 总结:我需要的是

  • a way to store some data persistently in a Web API backend without having to go off to a database 一种将一些数据持久存储在Web API后端中而无需转到数据库的方法
  • preferably store this data in a Dictionary object so I can use randomly-generated session IDs as the key, and an object to store the state 最好将这些数据存储在Dictionary对象中,这样我就可以使用随机生成的会话ID作为密钥,并使用一个对象来存储状态
  • the data is OK to be cleared after a set period of time or on a regular basis (not too frequently, maybe a minimum of a 6 hour persistence) 数据可以在一段时间后或定期清除( 不太频繁,可能至少持续6小时)

I figured out a solution using the Singleton pattern: 我找到了使用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;
    }        
}

It seems the Services.AppCache object successfully holds onto data until either the idle timeout expires or the application pool recycles. 似乎Services.AppCache对象成功保留数据,直到空闲超时到期或应用程序池回收为止。 Luckily I can control all of that in IIS, so I moved my app to its own AppPool and setup the idle timeout and recycling as appropriate, based on when I'm ok with the data being flushed. 幸运的是,我可以在IIS中控制所有这些,所以我将我的应用程序移动到它自己的AppPool并根据我正确刷新数据的情况,根据需要设置空闲超时和回收。

Sadly, if you don't have control over IIS (or can't ask the admin to set the settings for you), this may not work if the default expirations are too soon for you... At that point using something like a LocalDB file or even a flat JSON file might be more useful. 遗憾的是,如果您无法控制IIS(或者无法要求管理员为您设置设置),如果您的默认过期时间太短,则可能无效...此时使用类似于LocalDB文件甚至是扁平的JSON文件可能更有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM