一: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. background-attachment css3属性

    <style type="text/css"> body{ margin: 0; } .zhan{ width: 100%; height: 500px; backgr ...

  2. 关于编译PCL1.71

    最近在编译PCL1.71时总会出现错误, 编译的时候就出现无法生成pcl_io_debug.lib 由于无法生成pcl_io_debug.lib,. 借鉴PCL中国的经验: (1):把io\inclu ...

  3. 优动漫PAINT核心功能介绍

    优动漫PAINT是一款功能强大的动漫绘图软件,适用于个人和专业团队创作,分为个人版和EX版.搭载了绘制漫画和插画所需的所有功能——丰富的笔工具.超强的笔压感应和手颤修正功能,可分别满足画师对于插画.漫 ...

  4. 图片放大不失真软件PhotoZoom的工具栏

    PhotoZoom是一款极其简单的图片无损放大工具,简单几即可渲染出完美的放大照片,呈现无与伦比的画质效果.虽然简单,菜单和面板的功能很少,但却是设计师的必备神器,因为其简单易用性,它的软件菜单命令和 ...

  5. U盘启动盘安装Mac OS

    1.下载macOS High Sierra正式版 http://www.pc6.com/mac/gj_715_1.htm http://www.pc6.com/mac/518996.html 下载ma ...

  6. 微电影《Junior·BQB》——剧本

    电影名称:<Junior——BQB> 组长: 组员: 导演: 副导演: 分镜/演出: 编剧: 主演: 彬彬:比丘 阿伟:魔女(彬彬姐) 小怪:怪物团长 客串 旁白 友情演出: 恶俗之王 摄 ...

  7. Mysql插入语句.txt

    INSERT INTO 目标表 SELECT * FROM 来源表;比如要将 articles 表插入到 newArticles 表中,则是:INSERT INTO newArticles SELEC ...

  8. C#强化系列:HttpModule,HttpHandler,HttpHandlerFactory简单使用

    这三个对象我们在开发Asp.net程序时经常会用到,似乎很熟悉,但有时候又不太确定.本文通过一个简单的例子来直观的比较一下这三个对象的使用.HttpModule:Http模块,可以在页面处理前后.应用 ...

  9. 3、KOA模板引擎+访问静态资料中间件

    一.Koa模板引擎初识1.安装中间件 : npm i --save koa-views2.安装ejs模板引擎 :npm i --save ejs3.编写模板:<%= title %> 是调 ...

  10. 【codeforces 799C】Fountains

    [题目链接]:http://codeforces.com/contest/799/problem/C [题意] 你有两种不同的货币; 余额分别为c和d 然后有n种商品; 每种商品只能由两种货币中的某一 ...