一: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跨平台思路的更多相关文章

  1. Qt中如果通过QStyle自定义能够跨平台的界面控件

    我们经常会碰到需要定制界面控件的要求.如果只是在一个平台上,比如说你的控件只需要在Windows上显示,那很好办,Hard code 你的look and feel就可以了.但是如果界面需要在不同平台 ...

  2. 从一个简洁的进度刻度绘制中了解自定义View的思路流程

    先看效果(原谅我的渣像素),进度的刻度.宽度.颜色可以随意设定: [项目github地址: https://github.com/zhangke3016/CircleLoading] 实现起来并不难, ...

  3. 将form数据转换成json对象自定义插件实现思路

  4. Entity framework自定义字段实现思路

    ublic class MyModel { public int MyModelID { get; set; } public string FixedProperty1 { get; set; } ...

  5. ASP.NET跨平台最佳实践

    前言 八年的坚持敌不过领导的固执,最终还是不得不阔别已经成为我第二语言的C#,转战Java阵营.有过短暂的失落和迷茫,但技术转型真的没有想象中那么难.回头审视,其实单从语言本身来看,C#确实比Java ...

  6. Zabbix自定义监控8080端口的连接数

    Zabbix自定义监控8080端口的连接数 一 zabbix自定义监控实现思路 实际上我们要想使用zabbix来监控一些服务的原理很简单,步骤分别是:1.写一个脚本用于获取待监控服务的一些状态信息2. ...

  7. 使用VideoView自定义一个播放器控件

    介绍 最近要使用播放器做一个简单的视频播放功能,开始学习VideoView,在横竖屏切换的时候碰到了点麻烦,不过在查阅资料后总算是解决了.在写VideoView播放视频时候定义控制的代码全写在Actv ...

  8. ASP.NET MVC的TempData(转载)

    本文章基于ASP.NET MVC Preview5. ASP.NET MVC的TempData用于传输一些临时的数据,例如在各个控制器Action间传递临时的数据或者给View传递一些临时的数据,相信 ...

  9. activiti自定义流程之整合(一):整体环境配置

    结合之前所说的自定义流程的思路,分别是后台.前台.整合,之前的内容也分别进行了相关的练习和尝试,现在就该到了最后的整合了,依旧是以实现功能为目的,细节暂且不去管他. 因为我们实际项目后端用的是spri ...

随机推荐

  1. 电商物流仓储WMS业务流程

    电商物流仓储WMS业务流程 SKU是什么意思?  一文详解电商仓储管理中SKU的含义 从货品角度看,SKU是指单独一种商品,其货品属性已经被确定.只要货品属性有所不同,那么就是不同的SKU. PO信息 ...

  2. ubuntu下安装 nginx + php + memcached + mariadb

    一,apt-get 安装 1,安装nginx sudo apt-get install nginx 所有的配置文件都在/etc/nginx下,虚拟主机配置在/etc/nginx/sites-avail ...

  3. HTML5中新增加Input 的种类

    查询文本框 <input type="search"> 数字文本框 any 代表不设置 <input type="number" max=&q ...

  4. 后代children() find()的区别

    $(document).ready(function(){ $("div").children(); });只拿到div下面的子标签元素 $(document).ready(fun ...

  5. Pyhton学习——Day1

    1.什么是机器码?什么是字节码?机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据. 通常意义上来理解的话,机器码就是计 ...

  6. MySQL 单表查询多表查询

    一 单表查询 表准备 create table emp( id int not null unique auto_increment, name varchar(20) not null, sex e ...

  7. Disconf使用简单Demo

    创建配置文件 在敲Demo之前,需要在Disconf上创建自己的APP,然后在APP的某个环境下创建配置文件,如下面截图中的流程,这里就简单创建了一个redis.properties,内容是redis ...

  8. 莫烦大大TensorFlow学习笔记(8)----优化器

    一.TensorFlow中的优化器 tf.train.GradientDescentOptimizer:梯度下降算法 tf.train.AdadeltaOptimizer tf.train.Adagr ...

  9. 微信小程序:获取地理定位和显示相应的城市名称。

    最近在看微信小程序,遇到地理定位显示城市名称的问题.本文就是记录这一过程. 解决方案                                                          ...

  10. UOJ #86 mx的组合数 (数位DP+NTT+原根优化)

    题目传送门 matthew99神犇的题解讲得非常清楚明白,跪烂Orzzzzzzzzzzzzz 总结一下,本题有很多重要的突破口 1.Lucas定理 看到n,m特别大但模数特别小时,容易想到$lucas ...