自定义TempData跨平台思路
一:TempData的自定义实现。。。
TempData是用Session实现的,既然是Session,那模式是线程方式。。。这样的Session是没法进行跨平台的。。。
那么这就涉及到如何在多台机器上部署、存储...
- 关系型数据库: sqlserver/mysql
- nosql: mongodb,redis。
问题1:重点在替换,不在实现。。。。。怎么替换,以及使用方式
TempData继承关系:Tempdata => TempDataDictionary=> SessionStateTempDataProvider=>ITempDataProvider
namespace System.Web.Mvc
{
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc.Properties; public class SessionStateTempDataProvider : ITempDataProvider
{
internal const string TempDataSessionStateKey = "__ControllerTempData"; public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
HttpSessionStateBase session = controllerContext.HttpContext.Session;
if (session != null)
{
Dictionary<string, object> dictionary = session["__ControllerTempData"] as Dictionary<string, object>;
if (dictionary != null)
{
session.Remove("__ControllerTempData");
return dictionary;
}
}
return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
} public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
HttpSessionStateBase session = controllerContext.HttpContext.Session;
bool flag = (values != null) && (values.Count > );
if (session == null)
{
if (flag)
{
throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
}
}
else if (flag)
{
session["__ControllerTempData"] = values;
}
else if (session["__ControllerTempData"] != null)
{
session.Remove("__ControllerTempData");
}
}
}
}
SessionStateTempDataProvider类实现了ITempDataProvider接口,重写了Load和Save方法。
从源码可知,SessionStatesTempDataProvider暴露了LoadTempData和SaveTempData两个方法。
其中从SaveTempData中session["__ControllerTempData"] = (object) values;可以看出,TempData是存储在Session中的。
其中LoadTempData方法中session.Remove("__ControllerTempData");就说明了从session中获取tempdata后,对应的tempdata就从session中清空了
问题2:到底在mvc中哪个地方进行注入????mvc的管道中是怎么注入的???
MVC的管道和action方法执行前后发现:PossiblyLoadTempData和PossiblySaveTempData是在调用Controller中对应的action方法时执行的,并且Controller中有 TempDataProvider属性,代码如下:
public ITempDataProvider TempDataProvider
{
get
{
if (this._tempDataProvider == null)
{
this._tempDataProvider = this.CreateTempDataProvider();
}
return this._tempDataProvider;
}
set
{
this._tempDataProvider = value;
}
}
所以注入点就找到了,在创建Controller Factory中创建Controller实例的时候,把自定义的DataProvider类,赋值给TempDataProvider就可以了
下面来实现一把分布式的tempData
实现分布式流程
继承自DefaultControllerFactory的MyControllerFactory类即自定义的Controller Factory
public class MyControllerFactory:DefaultControllerFactory
{
public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
var iController= base.CreateController(requestContext, controllerName); var controller = iController as Controller;
controller.TempDataProvider = new CrossSessionTempData2(); return iController;
}
}
TempData的值存入到cache中之文件依赖
接着我们需要自定义一个实现了ITempDataProvider接口的DataProvider类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc; namespace CrossSessionTempData.Infrastructure
{
public class CrossSessionTempData2 : ITempDataProvider
{ internal const string TempDataSessionStateKey = "__ControllerTempData"; public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
var cache = controllerContext.HttpContext.Cache; if (cache != null)
{
Dictionary<string, object> dictionary = cache[TempDataSessionStateKey] as Dictionary<string, object>;
if (dictionary != null)
{
//cache.Remove(TempDataSessionStateKey);
return dictionary;
}
}
return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
} /// <summary>Saves the specified values in the temporary data dictionary by using the specified controller context.</summary>
/// <param name="controllerContext">The controller context.</param>
/// <param name="values">The values.</param>
/// <exception cref="T:System.InvalidOperationException">An error occurred the session context was being retrieved.</exception>
public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
var cache = controllerContext.HttpContext.Cache;
bool flag = values != null && values.Count > ;
if (cache == null)
{
if (flag)
{
throw new InvalidOperationException("");
}
}
else
{
CacheDependency dp = new CacheDependency(controllerContext.HttpContext.Server.MapPath("/Data/123.txt"));
if (flag)
{ //cache[TempDataSessionStateKey] = values;
cache.Insert(TempDataSessionStateKey, values, dp); return;
}
cache.Insert(TempDataSessionStateKey, values, dp);
//if (cache[TempDataSessionStateKey] != null)
//{
// cache.Remove(TempDataSessionStateKey);
//}
}
}
}
}
把TempData的值存入到NoSQL Memcached中实现真正的分布式
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Memcached.ClientLibrary; namespace WebDemo.Models
{
public static class MemcacheHelper
{
private static MemcachedClient mc; static MemcacheHelper()
{
//通过客户端来进行memcached的集群配置,在插入数据的时候,使用一致性哈希算法,将对应的value值存入Memcached
String[] serverlist = { "127.0.0.1:11211" }; // 初始化Memcached的服务池
SockIOPool pool = SockIOPool.GetInstance("test");
//设置服务器列表
pool.SetServers(serverlist);
//各服务器之间负载均衡的设置比例
pool.SetWeights(new int[] { });
pool.Initialize();
//创建一个Memcached的客户端对象
mc = new MemcachedClient();
mc.PoolName = "test";
//是否启用压缩数据:如果启用了压缩,数据压缩长于门槛的数据将被储存在压缩的形式
mc.EnableCompression = false; }
/// <summary>
/// 插入值
/// </summary>
/// <param name="key">建</param>
/// <param name="value">值</param>
/// <param name="expiry">过期时间</param>
/// <returns></returns>
public static bool Set(string key, object value,DateTime expiry){
return mc.Set(key, value, expiry);
}
/// <summary>
/// 获取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static object Get(string key)
{
return mc.Get(key);
}
}
}
自定义的我们的DataProvider:
public class CrossSessionTempData2 : ITempDataProvider
{ internal const string TempDataSessionStateKey = "__ControllerTempData"; public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{ Dictionary<string, object> dictionary = MemCaheHelper.Get(TempDataSessionStateKey) as Dictionary<string, object>;
if (dictionary != null)
{
MemCaheHelper.Set(TempDataSessionStateKey, dictionary, DateTime.MinValue);
return dictionary;
}
return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
} public virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
} bool flag = values != null && values.Count > ;
if (flag)
{ MemCaheHelper.Set(TempDataSessionStateKey, values,DateTime.Now.AddMinutes());
return;
} if (MemCaheHelper.Get(TempDataSessionStateKey) != null)
{
MemCaheHelper.Set(TempDataSessionStateKey,values,DateTime.MinValue);
} }
}
自定义TempData跨平台思路的更多相关文章
- Qt中如果通过QStyle自定义能够跨平台的界面控件
我们经常会碰到需要定制界面控件的要求.如果只是在一个平台上,比如说你的控件只需要在Windows上显示,那很好办,Hard code 你的look and feel就可以了.但是如果界面需要在不同平台 ...
- 从一个简洁的进度刻度绘制中了解自定义View的思路流程
先看效果(原谅我的渣像素),进度的刻度.宽度.颜色可以随意设定: [项目github地址: https://github.com/zhangke3016/CircleLoading] 实现起来并不难, ...
- 将form数据转换成json对象自定义插件实现思路
- Entity framework自定义字段实现思路
ublic class MyModel { public int MyModelID { get; set; } public string FixedProperty1 { get; set; } ...
- ASP.NET跨平台最佳实践
前言 八年的坚持敌不过领导的固执,最终还是不得不阔别已经成为我第二语言的C#,转战Java阵营.有过短暂的失落和迷茫,但技术转型真的没有想象中那么难.回头审视,其实单从语言本身来看,C#确实比Java ...
- Zabbix自定义监控8080端口的连接数
Zabbix自定义监控8080端口的连接数 一 zabbix自定义监控实现思路 实际上我们要想使用zabbix来监控一些服务的原理很简单,步骤分别是:1.写一个脚本用于获取待监控服务的一些状态信息2. ...
- 使用VideoView自定义一个播放器控件
介绍 最近要使用播放器做一个简单的视频播放功能,开始学习VideoView,在横竖屏切换的时候碰到了点麻烦,不过在查阅资料后总算是解决了.在写VideoView播放视频时候定义控制的代码全写在Actv ...
- ASP.NET MVC的TempData(转载)
本文章基于ASP.NET MVC Preview5. ASP.NET MVC的TempData用于传输一些临时的数据,例如在各个控制器Action间传递临时的数据或者给View传递一些临时的数据,相信 ...
- activiti自定义流程之整合(一):整体环境配置
结合之前所说的自定义流程的思路,分别是后台.前台.整合,之前的内容也分别进行了相关的练习和尝试,现在就该到了最后的整合了,依旧是以实现功能为目的,细节暂且不去管他. 因为我们实际项目后端用的是spri ...
随机推荐
- 第一个TensorFlow程序
第一个TensorFlow程序 TensorFlow的运行方式分为如下4步: (1)加载数据及定义超参数 (2)构建网络 (3)训练模型 (4)评估模型和进行预测 import tensorflow ...
- MongoDB_可视化工具Robo 3T
Robo 3T可以对MongoDB进行可视化操作. Robo 3T安装 官网下载地址:https://robomongo.org/ 进入官网,点击下载,Studio 3T功能更全面,基础功能是免费的, ...
- openlayers5学习笔记-001
tmp.initPoint = function (items) { //初始化所有农户点坐标,聚合 var count = items.length; var features = new Arra ...
- Matrix Matcher UVA - 11019AC_自动机 + 代价提前计算
Code: #include<cstdio> #include<cstring> #include<algorithm> #include<vector> ...
- TensorFlow实战学习笔记(14)------VGGNet
一.VGGNet:5段卷积[每段有2~3个卷积层+最大池化层][每段过滤器个数:64-128-256-512-512] 每段的2~3个卷积层串联在一起的作用: 2个3×3的卷积层串联的效果相当于一个5 ...
- Codeforces Round #468 (Div. 2, based on Technocup 2018 Final Round)B. World Cup
The last stage of Football World Cup is played using the play-off system. There are n teams left in ...
- 通过js 实现 向页面插入js代码并生效,和页面postMessage通讯
此文章针对已经搭建好jenkins和会使用iconfont图标库而写. 主要目标就是在不通过更改html文件,完成页面交互图标信息,因为美工最多可以上传代码并且自动发布,并不会在Html中加入我 ...
- nyoj11-奇偶数分离
奇偶数分离 时间限制:3000 ms | 内存限制:65535 KB 难度:1 描述 有一个整型偶数n(2<= n <=10000),你要做的是:先把1到n中的所有奇数从小到大输出,再 ...
- 作为深度学习最强框架的TensorFlow如何进行时序预测!(转)
作为深度学习最强框架的TensorFlow如何进行时序预测! BigQuant 2 个月前 摘要: 2017年深度学习框架关注度排名tensorflow以绝对的优势占领榜首,本文通过一个小例子介绍了T ...
- 深入MNIST code测试
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50624471 依照教程:深入MNIST ...