Overview
Due to the special mechanism of the WeChat public platform, all information is forwarded by the WeChat server, so the server cannot use Session to manage the context of the user session.
For this reason, Senparc.WeiXin.MP SDK adds a context module and integrates it into MessageHandler.
WeixinContext
WeixinContext is a container for all single user context (MessageContext) entities (tentatively called the global context). WeixinContext itself is not a static class, which means you can create multiple context entities in the same application.
At the same time, a static WeixinContext instance is put into MessageHandler
So in any instance that implements MessageHandler
WeixinContext is used to save the user's context (MessageContext) and provides a series of methods. The main methods include:
///
/// Reset all context parameters, all records will be cleared
///
public void Restore()
{
...
}
/// & lt; Summary & GT;
/// Get MESSAGECONTEXT, if it does not exist, return null
/// It is to operate the TM queue, remove expired information in time, and move the latest active objects to the end
///
/// Username ( OpenId)
## ///
/// Get MessageContext
///
/// Username (OpenId)< ;/param>
/// True: If the user does not exist, create an instance and return the latest instance
/// False: The user is stored in, Then return null
## ///
/// Get the MessageContext. If it does not exist, initialize one using the requestMessage information and return the original instance
///
///
public TM GetMessageContext(IRequestMessageBase requestMessage)
{
...
}
///
///
///
public TM GetMessageContext(IResponseMessageBase responseMessage)
{
...
}
///
to //
/// Request information
public void InsertMessage(IRequestMessageBase requestMessage)
{
...
}
">Response message
public void InsertMessage(IResponseMessageBase responseMessage)
{
...
}
///
/// Get the latest request data, if it does not exist, return Null
///
/// Username (OpenId)< /param>
/
/// Get the latest response data, if it does not exist, return Null
///
///
WeixinContext has two objects used to store user context: MessageCollection and MessageQueue.
The element collections in these two objects overlap, but the MessageQueue sorts the elements so that the top expired context can be processed in a timely manner.
ExpireMinutes is used to define the context time validity period, the default is 90 minutes. You can set a parameter anywhere in the program and it will take effect immediately.
PS: The logic of deleting expired data in MessageQueue operates with extremely high efficiency. There is no need to consider CPU usage and object conflicts (whether the additional verification time times out) during regular development.
MessageContext
MessageContext is used to save the context information of a single user and is stored in the MessageCollection and MessageQueue objects of WeixinContext. IMessageContext is defined as follows:
/// <summary> /// 微信消息上下文(单个用户)接口 /// </summary> /// <typeparam name="TRequest">请求消息类型</typeparam> /// <typeparam name="TResponse">响应消息类型</typeparam> public interface IMessageContext<TRequest,TResponse> where TRequest : IRequestMessageBase where TResponse : IResponseMessageBase { /// <summary> /// 用户名(OpenID) /// </summary> string UserName { get; set; } /// <summary> /// 最后一次活动时间(用户主动发送Resquest请求的时间) /// </summary> DateTime LastActiveTime { get; set; } /// <summary> /// 接收消息记录 /// </summary> MessageContainer<TRequest> RequestMessages { get; set; } /// <summary> /// 响应消息记录 /// </summary> MessageContainer<TResponse> ResponseMessages { get; set; } /// <summary> /// 最大储存容量(分别针对RequestMessages和ResponseMessages) /// </summary> int MaxRecordCount { get; set; } /// <summary> /// 临时储存数据,如用户状态等,出于保持.net 3.5版本,这里暂不使用dynamic /// </summary> object StorageData { get; set; } /// <summary> /// 用于覆盖WeixinContext所设置的默认过期时间 /// </summary> Double? ExpireMinutes { get; set; } /// <summary> /// AppStore状态,系统属性,请勿操作 /// </summary> AppStoreState AppStoreState { get; set; } event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageContextRemoved; void OnRemoved(); }
You can create your own class according to your own needs, implement this interface, and be used by WeixinContext. Of course, if your requirements are not so special and you are lazy, the SDK provides a default MessageContext implementation:
/// <summary> /// 微信消息上下文(单个用户) /// </summary> public class MessageContext<TRequest,TResponse>: IMessageContext<TRequest, TResponse> where TRequest : IRequestMessageBase where TResponse : IResponseMessageBase { private int _maxRecordCount; public string UserName { get; set; } public DateTime LastActiveTime { get; set; } public MessageContainer<TRequest> RequestMessages { get; set; } public MessageContainer<TResponse> ResponseMessages { get; set; } public int MaxRecordCount { get { return _maxRecordCount; } set { RequestMessages.MaxRecordCount = value; ResponseMessages.MaxRecordCount = value; _maxRecordCount = value; } } public object StorageData { get; set; } public Double? ExpireMinutes { get; set; } /// <summary> /// AppStore状态,系统属性,请勿操作 /// </summary> public AppStoreState AppStoreState { get; set; } public virtual event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageContextRemoved = null; /// <summary> /// 执行上下文被移除的事件 /// 注意:此事件不是实时触发的,而是等过期后任意一个人发过来的下一条消息执行之前触发。 /// </summary> /// <param name="e"></param> private void OnMessageContextRemoved(WeixinContextRemovedEventArgs<TRequest, TResponse> e) { EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> temp = MessageContextRemoved; if (temp != null) { temp(this, e); } } /// <summary> /// /// </summary> /// <param name="maxRecordCount">maxRecordCount如果小于等于0,则不限制</param> public MessageContext(/*MessageContainer<IRequestMessageBase> requestMessageContainer, MessageContainer<IResponseMessageBase> responseMessageContainer*/) { /* * 注意:即使使用其他类实现IMessageContext, * 也务必在这里进行下面的初始化,尤其是设置当前时间, * 这个时间关系到及时从缓存中移除过期的消息,节约内存使用 */ RequestMessages = new MessageContainer<TRequest>(MaxRecordCount); ResponseMessages = new MessageContainer<TResponse>(MaxRecordCount); LastActiveTime = DateTime.Now; } public virtual void OnRemoved() { var onRemovedArg = new WeixinContextRemovedEventArgs<TRequest, TResponse>(this); OnMessageContextRemoved(onRemovedArg); } }
The above code is easy to understand based on the comments. What needs to be explained is StorageData. This is a container used to store any data related to the user context. WeixinContext and IMessageContext do not have any reference to it. It is entirely up to the developer to determine the content (such as which step the user has taken, or some important location information, etc. etc.), similar to the role of Session.
The above MessageContext
public class CustomMessageContext : MessageContext<IRequestMessageBase,IResponseMessageBase> { public CustomMessageContext() { base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved; } /// <summary> /// 当上下文过期,被移除时触发的时间 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void CustomMessageContext_MessageContextRemoved(object sender, Senparc.Weixin.Context.WeixinContextRemovedEventArgs<IRequestMessageBase,IResponseMessageBase> e) { /* 注意,这个事件不是实时触发的(当然你也可以专门写一个线程监控) * 为了提高效率,根据WeixinContext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除 */ var messageContext = e.MessageContext as CustomMessageContext; if (messageContext == null) { return;//如果是正常的调用,messageContext不会为null } //TODO:这里根据需要执行消息过期时候的逻辑,下面的代码仅供参考 //Log.InfoFormat("{0}的消息上下文已过期",e.OpenId); } }
The above CustomMessageContext_MessageContextRemoved() method will be Triggered when a user's context is cleared, you can add the code you need. In addition, you can also override methods such as OnRemoved() in accumulation, or add other attributes and methods.
For more articles related to WeChat public platform development: solving user context (Session) issues, please pay attention to the PHP Chinese website!