自定义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 ...
随机推荐
- 使用JDK和axis2发布webservice
最近使用webservice进行远程调用一直很火,自从JDK1.6版本发布后,发布一个webservice项目变得更加简单了 笔者由于工作的需要针对JDK和axis2如何发布webservice做过相 ...
- 开源作品-ThinkPHP在线分析工具(单文件绿色版)-TPLogAnalysis_PHP_1_0
TPLogAnalysis_PHP_1_0 前言:项目开发基于ThinkPHP框架,但是在调试程序的时候,没有一款日志可视化分析工具.在网络也找不到任何相关的TP日志分析工具.求人不如求己,于是决定抽 ...
- svn SSL 错误:Key usage violation in certificate has been detected
CentOS/RHEL yum 安装的 subversion 是 1.6.11 版本,连VisualSVN服务器时会有"Key usage violation"的错误 将subve ...
- Vs2010无法打开文件“Kernel32.lib”、无法打开“libcpmt.lib”"msvcprt.lib"
1.对于无法打开"Kernel"问题,即使复制lib文件到目录,仍然会出现最后的错误; 原因:WindowsSdk 安装失败! 方法:重装 microsoft SDK6.0 ,再在 ...
- img标签过滤加fs模块实现图片文件缓存
方法一:function iCache(selector) { selector.each(function(data) { //msg(data); ! function(data) { var u ...
- Vue中的v-model与my97日期选择插件冲突
Vue中的v-model指令只是一个语法糖,其具体实现是:监听input框的input事件,然后将用户输入的值赋值给input框的value属性 <input type="text&q ...
- MySQL主主高可用(keepalive)
2台新的虚拟机172.16.1.1.172.16.1.2 (配置yum源 ) 安装数据库服务 其中 172.16.1.1.172.16.1.2运行数据库服务并设置数据库管理员从本机登录的密码是xzw ...
- spring重点一:处理对象创建时间 个数以及方式
/** * 1) 对象创建: 单例/多例(个数) * scope="singleton", 默认值, 即 默认是单例 [service/dao/工具类] * scope=&quo ...
- linux--ubuntu的下载以及VMware Tool的安装
1. Ubuntu的下载:http://cn.ubuntu.com/download/ 2. VMware Tool的安装: 第一步:在主机上,从 Workstation Pro 菜单栏中选择虚拟机 ...
- 【模板】最大流模板(dinic)
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...