自定义缓存无法在Child Actions中运行

时间:2013-10-22 17:21:36

标签: c# asp.net asp.net-mvc

我正在使用一个自定义类,单独为移动页面和普通页面输出cche。我只缓存索引页面。它在使用索引页面进行缓存时非常有效。但是当使用子操作时,会抛出以下错误:

Server Error in '/' Application.

Unable to cast object of type 'System.IO.StringWriter' to type 'System.Web.HttpWriter'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidCastException: Unable to cast object of type 'System.IO.StringWriter' to type 'System.Web.HttpWriter'.

Source Error: 


Line 82:                         sw = new StringWriter(sb);
Line 83:                         tw = new HtmlTextWriter(sw);
Line 84:                         output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output;
Line 85:                         filterContext.RequestContext.HttpContext.Response.Output = tw;
Line 86:                     }

Source File: H:\Yazılımlar\Haber Sitesi v2\HaberSitesiV2\HaberSitesiV2\Filters\CustomCacheAttribute.cs    Line: 84 

Stack Trace: 


[InvalidCastException: Unable to cast object of type 'System.IO.StringWriter' to type 'System.Web.HttpWriter'.]
   HaberSitesiV2.Filters.CustomCacheAttribute.OnActionExecuting(ActionExecutingContext filterContext) in H:\Yazılımlar\Haber Sitesi v2\HaberSitesiV2\HaberSitesiV2\Filters\CustomCacheAttribute.cs:84
   System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +69
   System.Web.Mvc.Async.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35() +21
   System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +489
   System.Web.Mvc.Async.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35() +21
   System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) +489
   System.Web.Mvc.Async.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35() +21
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__31(AsyncCallback asyncCallback, Object asyncState) +191
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters, AsyncCallback callback, Object state) +197
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +446
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +302
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71
   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.Mvc.<>c__DisplayClass7.<BeginProcessRequest>b__6() +31
   System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +27
   System.Web.Mvc.ServerExecuteHttpHandlerAsyncWrapper.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +98
   System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +2019
   System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +76
   System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +28
   System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +19
   System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +483
   System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) +83
   System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName) +10
   ASP._Page_Views_Anasayfa_Index_cshtml.Execute() in h:\Yazılımlar\Haber Sitesi v2\HaberSitesiV2\HaberSitesiV2\Views\Anasayfa\Index.cshtml:29
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +197
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +97
   System.Web.WebPages.StartPage.RunPage() +17
   System.Web.WebPages.StartPage.ExecutePageHierarchy() +62
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +76
   System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +260
   System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +115
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +295
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
   System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +23
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +242
   System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +21
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +242
   System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +21
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +177
   System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +89
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +102
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +43
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +57
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +47
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +25
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +47
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629708
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929

我的课程也随之而来。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Web.UI;
using System.Web.WebPages;

namespace HaberSitesiV2.Filters
{
    public enum CachePolicy
    {
        NoCache = 0,
        Client = 1,
        Server = 2,
        ClientAndServer = 3
    }

    public class CustomCacheAttribute : ActionFilterAttribute
    {
        #region Public properties

        public string VaryByParam { get; set; }
        public CachePolicy CachePolicy { get; set; }

        #endregion

        #region Private members

        private HtmlTextWriter tw;
        private StringWriter sw;
        private StringBuilder sb;
        private HttpWriter output;
        private bool cacheHitNormal = false;
        private bool cacheHitMobile = false;
        #endregion

        #region ActionFilterAttribute overrides


        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Server-side caching?
            if (CachePolicy == CachePolicy.Server || CachePolicy == CachePolicy.ClientAndServer)
            {
                if (filterContext.HttpContext.Application["cacheSql"] != null)
                {
                    // Fetch cached data
                    string key = GenerateKey(filterContext);
                    object cachedData = HttpContext.Current.Cache.Get(key);
                    if (cachedData != null)
                    {
                        // cache hit
                        if (filterContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)
                            cacheHitMobile = true;
                        else
                        cacheHitNormal = true;
                        // Return cached data
                        filterContext.HttpContext.Response.Write(cachedData);
                        filterContext.Result = new EmptyResult();
                    }
                    else
                    {
                        // Cache not hit.
                        if (filterContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)
                            cacheHitMobile = false;
                        else
                        cacheHitNormal = false;
                        //
                        sb = new StringBuilder();
                        sw = new StringWriter(sb);
                        tw = new HtmlTextWriter(sw);
                        output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output;
                        filterContext.RequestContext.HttpContext.Response.Output = tw;
                    }
                }
            }
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            // Server-side caching?
            if (CachePolicy == CachePolicy.Server|| CachePolicy == CachePolicy.ClientAndServer)
            {
                if (filterContext.HttpContext.Application["cacheSql"] != null)
                {
                    if (filterContext.HttpContext.GetOverriddenBrowser().IsMobileDevice ? !cacheHitMobile : !cacheHitNormal)
                    {
                        int duration = 0;
                            duration = Convert.ToInt32(filterContext.HttpContext.Application["cacheSql"]);
                        //response processing
                        output.Write(sb.ToString());
                        // Add data to cache
                        HttpContext.Current.Cache.Insert(
                            GenerateKey(filterContext),
                            sb.ToString(),
                            null,
                            DateTime.Now.AddMinutes(duration),
                            Cache.NoSlidingExpiration,
                            CacheItemPriority.Normal,
                            null);
                    }
              }
            }
        }
        #endregion

        #region Helper methods
        private string GenerateKey(ControllerContext filterContext)
        {
            StringBuilder cacheKey = new StringBuilder();

            // Controller + action
            cacheKey.Append(filterContext.Controller.GetType().FullName);
            if (filterContext.RouteData.Values.ContainsKey("action"))
            {
                cacheKey.Append("_");
                cacheKey.Append(filterContext.RouteData.Values["action"].ToString());
            }

            // Variation by parameters
            List<string> varyByParam = VaryByParam.Split(';').ToList();

            if (!string.IsNullOrEmpty(VaryByParam))
            {
                foreach (KeyValuePair<string, object> pair in filterContext.RouteData.Values)
                {
                    if (VaryByParam == "*" || varyByParam.Contains(pair.Key))
                    {
                        cacheKey.Append("_");
                        cacheKey.Append(pair.Key);
                        cacheKey.Append("=");
                        cacheKey.Append(pair.Value.ToString());
                    }
                }
            }
            cacheKey.Append("_");
            cacheKey.Append(filterContext.HttpContext.GetOverriddenBrowser().IsMobileDevice ? "mobil" : "normal");
            return cacheKey.ToString();
        }

        #endregion
    }
}

0 个答案:

没有答案