ASP.NET MVC“Donut caching”和TempData
是否有任何解决方案来访问HttpResponseBase.WriteSubstitution()方法中的TempData属性
这不起作用: <%= Response.WriteSubstitution(x => Html.Encode(TempData["message"].ToString())) %> 但这有效: <%= Response.WriteSubstitution(x => DateTime.Now.ToString()) %> 问题出在一次缓存页面的请求处理中.根据http://msdn.microsoft.com/en-us/library/system.web.httpresponse.writesubstitution.aspx:
换句话说,委托无权访问Session属性(SessionStateTempDataProvider在会话中存储TempData),因为没有“正常”的请求生命周期.据我所知,它是在HttpApplication.ResolveRequestCache / HttpApplication.PostResolveRequestCache事件中处理的,但当前状态是在HttpApplication.AcquireRequestState事件中获取的(http://msdn.microsoft.com/en-us/library/ms178473.aspx) 也许我需要某种“高级自定义TempDataProvider”:)任何想法? 解决方法
我找到了解决方案:
主要思想是在缓存中保存TempData的副本,并在每个请求中进行检索.该解决方案是自定义TempDataProvider和简单http模块的组合.另外还有几个助手和静态类. 这是代码: CustomTempDataProvider: using System; using System.Collections.Generic; using System.Web; using System.Web.Caching; using System.Web.Mvc; public class CustomTempDataProvider : SessionStateTempDataProvider,IHttpModule { public void Init(HttpApplication application) { application.BeginRequest += new EventHandler(application_BeginRequest); } void application_BeginRequest(object sender,EventArgs e) { var httpContext = HttpContext.Current; var tempData = httpContext.Cache[TempDataKey] ?? new Dictionary<string,object>(StringComparer.OrdinalIgnoreCase); httpContext.Items.Add("TempData",tempData); httpContext.Cache.Remove(TempDataKey); } public override void SaveTempData(ControllerContext controllerContext,IDictionary<string,object> values) { HttpContext.Current.Cache.Insert(TempDataKey,values,null,DateTime.Now.AddMinutes(5),Cache.NoSlidingExpiration,CacheItemPriority.NotRemovable,null); base.SaveTempData(controllerContext,values); } public static string TempDataKey { get { string sessionID = "0"; var httpContext = HttpContext.Current; if(httpContext.Session != null) { sessionID = httpContext.Session.SessionID; } else if (httpContext.Request.Cookies["ASP.NET_SessionId"] != null) { sessionID = httpContext.Request.Cookies["ASP.NET_SessionId"].Value; } return "TempData-For-Session-" + sessionID; } } public void Dispose() { } } 在web.config中注册它: <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <httpModules> <add name="CustomTempDataProvider" type="CustomTempDataProvider" /> </httpModules> </system.web> <system.webServer> <modules> <remove name="CustomTempDataProvider" /> <add name="CustomTempDataProvider" type="CustomTempDataProvider" /> </modules> </system.webServer> </configuration> CustomControllerFactory: using System.Web.Routing; using System.Web.Mvc; public class CustomControllerFactory : DefaultControllerFactory { public override IController CreateController( RequestContext requestContext,string controllerName) { var controller = (Controller)base.CreateController(requestContext,controllerName); controller.TempDataProvider = new CustomTempDataProvider(); return controller; } } 在Global.asax中注册它: protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory)); } 用于访问TempData的静态类: using System; using System.Collections.Generic; using System.Linq; using System.Web; public static class CustomTempData { public static object Get(string key) { var tempData = HttpContext.Current.Items["TempData"] as IDictionary<string,object>; var item = tempData.FirstOrDefault(x => x.Key == key).Value ?? String.Empty; return item; } } 用于缓存后替换的助手: using System; using System.Web; using System.Web.Mvc; public static class Html { public delegate object MvcResponseSubstitutionCallback(HttpContextBase context); public static object MvcResponseSubstitute(this HtmlHelper html,MvcResponseSubstitutionCallback callback) { html.ViewContext.HttpContext.Response.WriteSubstitution( context => HttpUtility.HtmlEncode( (callback(new HttpContextWrapper(context)) ?? String.Empty).ToString() ) ); return null; } } 现在这成功了: <h3><%= Html.MvcResponseSubstitute(context => CustomTempData.Get("message")) %></h3> 如果您了解俄语,请阅读this 希望这可以帮助 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- C# 快速高效率复制对象另一种方式 表达式树
- 数组 – ASP MVC控制器动作可以接收一个byte []吗?
- 使用ASP.NET开发服务器测试多个域
- asp.net – 如果Ninject尚未绑定,如何在Ninject中绑定?
- asp.net – 具有绝对URL的Asp .Net MVC RedirectToAction
- asp.net – Application_Start和Application_OnStart之间的
- asp.net-mvc-3 – 内部模型的自定义模型绑定器
- asp.net-mvc – 如何编写C#Extension方法将Domain Model对象
- asp.net-mvc-4 – 始终显示在Kendo网格中选择的第一行
- 定时器_在.net core3.0 webapi中添加自定义定时器功能