Git Product home page Git Product logo

moonpyk / mvcdonutcaching Goto Github PK

View Code? Open in Web Editor NEW
142.0 16.0 49.0 2.02 MB

ASP.NET MVC Extensible Donut Caching brings donut caching to ASP.NET MVC 3 and later. The code allows you to cache all of your page apart from one or more Html.Actions which can be executed every request. Perfect for user specific content.

Home Page: https://github.com/moonpyk/mvcdonutcaching

License: MIT License

C# 94.93% CSS 4.95% ASP 0.10% Batchfile 0.01%
aspnet aspnet-mvc-5 caching

mvcdonutcaching's Introduction

ASP.NET MVC Extensible Donut Caching

ASP.NET MVC Extensible Donut Caching brings donut caching to ASP.NET MVC 3 and later. The code allows you to cache all of your page apart from one or more Html.Actions which can be executed every request. Perfect for user specific content.

Build status

Download

The best way to add donut caching to your MVC project is to use the NuGet package. From within Visual Studio, select Tools | Library Package Manager and then choose either Package Manager Console or Manage NuGet Packages. Via the console, just type install-package MvcDonutCaching and hit return. From the GUI, just search for MvcDonutCaching and click the install button.

Usage

The package adds several overloads to the built-in Html.Action HTML helper. The extra parameter in each overload is named excludeFromParentCache. Set this to true for any action that should not be cached, or should have a different cache duration from the rest of the page.

@Html.Action("Login", "Account", true)

The package also include a DonutOutputCacheAttribute to be used in place of the built-in OutputCacheAttribute. This attribute is typically placed on every controller action that needs be be cached.

You can either specify a fixed duration:

[DonutOutputCache(Duration = "300")]
public ActionResult Index()
{
	return View();
}

Or, use a cache profile:

[DonutOutputCache(CacheProfile = "FiveMins")]
public ActionResult Index()
{
  	return View();
}

If you are using cache profiles, be sure to configure the profiles in the web.config. Add the following within the system.web element:

<caching>
  <outputCacheSettings>
    <outputCacheProfiles>
      <add name="FiveMins" duration="300" varyByParam="*" />
    </outputCacheProfiles>
  </outputCacheSettings>
</caching>

You can also configure the output cache to use a custom provider:

<caching>
  <outputCache defaultProvider="DistributedCacheProvider">
    <providers>
      <add name="DistributedCacheProvider" type="DevTrends.Example.DistributedCacheProvider" />
    </providers>
  </outputCache>
</caching>

Note, that a custom provider is not included with this project but you can write one fairly easily by subclassing System.Web.Caching.OutputCacheProvider. A number of implementations are also available on the web.

More Information

A comprehensive guide to MVC Extensible Donut Caching is now available on the DevTrends Blog.

mvcdonutcaching's People

Contributors

anorborg avatar blanciq avatar devtrends avatar gaspardle avatar gplesz avatar mlidbom avatar moonpyk avatar polyakova avatar yazgoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mvcdonutcaching's Issues

Support actions being invoked through external infrastructure, not HtmlHelper.Action

Thinking out loud here:

We are working with a CMS that calls controller methods directly in quite a few cases. We must disable caching for large parts of views that could otherwise be cached to ensure that these parts are not cached.

As a fix I've been playing around with the idea of getting rid of the need for the overload of HtmlHelper.Action. it would go something like this in OnActionExecuting:

if(controllerMethod.CachePolicy != parentControllerMethod.CachePolicy){
    renderSurroundedByDonut....
}else{
    renderWithoutDonut...
}

Applying the attributes would make everything "just work" without having to chase down all usages.

If this would be problematic as the default it could be a configurable option or a separate attribute to enable this behavior.

What do you think?
Would you be willing to consider merging a pull request implementing that?

Why GetVaryByCustomString execute twice?

I'm add a custom cache for my child Action

[DonutOutputCache(CacheProfile = "Static")]
 [ChildActionOnly]
public ActionResult LeftNavigator()
{
      return PartialView("Navigation");
}

Then continue change the web.config

<caching>
      <outputCacheSettings>
        <outputCacheProfiles>
          <clear />
          <!-- 8 hour-->
          <add varyByCustom="Static" varyByParam="*" duration="28800" name="Static" location="Server" />
        </outputCacheProfiles>
      </outputCacheSettings>
    </caching>

Finally go to global.asax override GetVaryByCustomString

public override string GetVaryByCustomString(HttpContext context, string arg)
        {
            if (arg == "Static")
            {
                return "Static=" + HttpContext.Current.Session.SessionID;
            }

            return base.GetVaryByCustomString(context, arg);
        }

But when I debug, every request, the GetVaryByCustomString be call twice. Why? Is that a BUG?
I'm using the new version on .net 4.5 mvc 5. thanks.

Action Key Generation Area/Action Confusion

I have 2 HomeController(s) based upon your demo.
The only difference is that they are in different areas

Both Index() actions get called correctly.
/Sports and /Free get routed correctly

Both Index() actions redirect to Simple()
Once the first Simple() action is called that is the one that is cached for everyone. No Simple() action in either of these controllers is ever called again for the duration of the cache.

It appears that there is an issue with cache key confusion here. Could be related to someone asking for area support. Anyway, showstopper for me..

namespace Pingo.Demo.Area.Areas.Sports.Controllers 
{
    public class HomeController : Controller
    {
      //
      // GET: /Sports/Home/

      public ActionResult Index()
      {
              return RedirectToAction("Simple");
      }

      [DonutOutputCache(Duration = 24 * 3600)]
      public ActionResult Simple()
      {
          return View(DateTime.Now);
      }
   } 
}

namespace Pingo.Demo.Area.Areas.Free.Controllers 
{
    public class HomeController : Controller
    {
        //
        // GET: /Free/Home/

        public ActionResult Index()
        {
            return RedirectToAction("Simple");
        }

        [DonutOutputCache(Duration = 24 * 3600)]
        public ActionResult Simple()
        {
         return View(DateTime.Now);
        }
    }
} 

Added the following;

controllerName = context.Controller.ToString();

You are building a key simply based upon the controller name, i.e. Home.
You should be building it using the full controller name, i.e. {namespace}.{class}

Fixed my problem, but I don't want maintain my own branch :(

namespace DevTrends.MvcDonutCaching
{
    public class KeyGenerator : IKeyGenerator
    {
         public string GenerateKey(ControllerContext context, CacheSettings cacheSettings)
         {
              ....
              controllerName = context.Controller.ToString();
              var key = _keyBuilder.BuildKey(controllerName, actionName, routeValues);

              return key;
         }
    }
}

Unit tests suite

Unit tests should be written to guaranty package stability.

Chosen technology : xUnit.net

abstract controller class derived as regular controllers in two different areas hits same cache

public abstract class AbstractProtocolController : Controller {
        ...
        [DonutOutputCache(Duration = 300, VaryByParam = "id", Location = OutputCacheLocation.Server)] 
        public ActionResult Detail(int id)
        {
             ...
        }
        ...
}

This abstract controller class is implemented in two concrete classes in separate areas.
When I do a web request to the action in the first area and then to the other action in the second area the view from the first area is served from cache. A note the concrete classes have the same controllername, but this shouldn't be an issue since they are still in two different areas.

I have only tested this out with the current pre-release version on NuGet (MvcDonutCaching 1.3.1-rc1).

How to use with RenderPartial?

I want to cache a controller/action page, but I do not want to cache a certain RenderPartial since it display's login info. I couldn't find an overloaded parameter on RenderPartial. Is this possible?

MvcDonutCaching doesn't work on ChildActions?

I'm using MVC 5.2.3.
I have a PartialView that I used it in _Layout.cshtml as the following:
@Html.Action("TopMenu", "Home", true)
But MvcDonutCaching doesn't work and TopMenu get cached as normal

[ChildActionOnly]
[DonutOutputCache(Duration = 60)]
public PartialViewResult TopMenu()
{
    return PartialView("~/Views/Partials/TopMenuPartial.cshtml");
}

Pick CacheProvider in runtime

What do I do if I want to pick CacheProvider in runtime?
In the standard implementation could override GetOutputCacheProviderName in Global.asax

500 error when writing to the response stream

I have a "ImageResult" actionresult that I use to send database stored images to the browser and since these shouldn't be changing too much is only logical to cache them.

Code below is overriden ExecuteResult. COntentType and the byte stream come from database and everything works without the DonutOutputCache attribute.
It even worked on the default OutputCache attribute, but I need to clear this cache item if the user changes his profile image, so no default OutputCache for me

        var response = context.HttpContext.Response;
        response.Clear();
        response.ContentType = ContentType;

        var stream = new MemoryStream(ImageBytes);
        stream.WriteTo(response.OutputStream);
        stream.Dispose();

Here is the exception log entry. Any way to work around this?

2014-01-06 01:32:56,752 [6] ERROR CoachDota.ImageResult Error writing byte stream to response stream
System.Web.HttpException (0x80004005): OutputStream is not available when a custom TextWriter is used.
at System.Web.HttpResponse.get_OutputStream()
at System.Web.HttpResponseWrapper.get_OutputStream()
at CoachDota.ImageResult.ExecuteResult(ControllerContext context) in F:\VSPROJ\CoachDota\CoachDota\Code\Common\ImageResult.cs:line 46

Action that takes ViewDataDictionary as parameter in Html.RenderAction breaks serialiser

Seems the data contract serializer does not work with ViewDataDictionary. Is this true? Or am I doing something wrong?

ex: Html.RenderAction(MVC.Global.Footer(ViewData), true);

DevTrends.MvcDonutCaching.ActionSettingsSerialiser.Serialise(ActionSettings actionSettings) in c:\Users\moonpyk\Documents\Visual Studio 2012\Projects\mvcdonutcaching\DevTrends.MvcDonutCaching\ActionSettingsSerialiser.cs:22

Type 'System.Web.Mvc.ViewDataDictionary`1, Version=1.1.5.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfKeyValueOfstringanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Caching Response Headers

Hello,

is it possible to cache response headers which are set via custom ActionFilter's?

Our application has a ActionFilter which set's the Content-Range header by inspecting the view model. This header get's lost when donut caching is serving the site from cache.

Thank you!

ASP MVC Demo project

An ASP.NET demo project should be written featuring usage of MvcDonutCaching.

  • Basic usage
  • Cache invalidation techniques
  • Usage with DI container (Autofac)
  • Custom provider demo

Filtering is not allowed

When using MvcDonutCaching in combination with a Response.Filter the execution breaks.

E.g. I'm using a filter to minify the html output before it's sent to the client. This is done by:

public class HtmlCompressFilterAttribute : ActionFilterAttribute
    {   
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Response.ContentType.ToLower().Contains("text/html"))
            {
                filterContext.HttpContext.Response.Filter = new HtmlCompressorFilter(filterContext.HttpContext.Response.Filter);
                base.OnActionExecuting(filterContext);
            }
        }
    }

When using this in combination with MvcDonutCaching the code breaks with the error:

System.Web.HttpException (0x80004005): Filtering is not allowed.
   at System.Web.HttpResponse.set_Filter(Stream value)

Server crash on creating cache item

Hi,
I've just implement MVCdonutcaching for my web apps. Everytime (~20-30 times) I browse app with donutcaching enable, server was freeze for a few secs then continue to work. But when I clear all cache item then refresh the browser, it's freeze again. I used MongoDBOutputCache but it's still happens with origin MVCDonutcaching.

I have check event viewer and this's what i got from it:
"Windows successfully diagnosed a low virtual memory condition. The following programs consumed the most virtual memory: vbc.exe (3644) consumed 8264318976 bytes, mongod.exe (2948) consumed 2925314048 bytes, and devenv.exe (6016) consumed 900939776 bytes.".
My server has 8GB DDR3 with SSD, application run fluently with no delay without donutcaching.
Anyway to fix that?
Thanks.

Null reference exception

It recently appeared, not really sure why. The error is random (impossible to reproduce), so probably it's a race condition or browser related. I'm unable to reproduce the error myself. I got 14 occurences accross only 3 IP, all having "Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)" as user agent and very strange post data (see below).
It's not a big issue (nasty spider), but the exception shouldn't be thrown away.

NullReferenceException: Object reference not set to an instance of an object.

1 File "DevTrends.MvcDonutCaching.KeyGenerator" line 220 in GenerateKey(System.Web.Mvc.ControllerContext context, DevTrends.MvcDonutCaching.CacheSettings cacheSettings)
2 File "DevTrends.MvcDonutCaching.DonutOutputCacheAttribute" line 0 in ExecuteCallback(System.Web.Mvc.ControllerContext context, System.Boolean hasErrors)
3 File "System.Web.Mvc.ControllerActionInvoker" line 29 in InvokeExceptionFilters(System.Web.Mvc.ControllerContext controllerContext, System.Collections.Generic.IList`1[System.Web.Mvc.IExceptionFilter] filters, System.Exception exception)
4 File "System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass21" line 693 in <BeginInvokeAction>b__19(System.AsyncCallback asyncCallback, System.Object asyncState)
5 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 38 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
6 File "System.Web.Mvc.Async.AsyncResultWrapper" line 11 in Begin(System.AsyncCallback callback, System.Object state, System.Web.Mvc.Async.BeginInvokeDelegate beginDelegate, System.Web.Mvc.Async.EndInvokeDelegate`1[TResult] endDelegate, System.Object tag, System.Int32 timeout)
7 File "System.Web.Mvc.Async.AsyncControllerActionInvoker" line 199 in BeginInvokeAction(System.Web.Mvc.ControllerContext controllerContext, System.String actionName, System.AsyncCallback callback, System.Object state)
8 File "System.Web.Mvc.Controller" line 33 in <BeginExecuteCore>b__1c(System.AsyncCallback asyncCallback, System.Object asyncState, System.Web.Mvc.Controller+ExecuteCoreState innerState)
9 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1" line 0 in CallBeginDelegate(System.AsyncCallback callback, System.Object callbackState)
10 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 38 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
11 File "System.Web.Mvc.Async.AsyncResultWrapper" line 14 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
12 File "System.Web.Mvc.Controller" line 241 in BeginExecuteCore(System.AsyncCallback callback, System.Object state)
13 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 44 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
14 File "System.Web.Mvc.Async.AsyncResultWrapper" line 24 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
15 File "System.Web.Mvc.Controller" line 165 in BeginExecute(System.Web.Routing.RequestContext requestContext, System.AsyncCallback callback, System.Object state)
16 File "System.Web.Mvc.MvcHandler" line 34 in <BeginProcessRequest>b__4(System.AsyncCallback asyncCallback, System.Object asyncState, System.Web.Mvc.MvcHandler+ProcessRequestState innerState)
17 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1" line 14 in CallBeginDelegate(System.AsyncCallback callback, System.Object callbackState)
18 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 44 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
19 File "System.Web.Mvc.Async.AsyncResultWrapper" line 24 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
20 File "System.Web.Mvc.MvcHandler" line 189 in BeginProcessRequest(System.Web.HttpContextBase httpContext, System.AsyncCallback callback, System.Object state)
21 File "System.Web.HttpApplication+CallHandlerExecutionStep" line 451 in System.Web.HttpApplication.IExecutionStep.Execute
22 File "System.Web.HttpApplication" line 60 in ExecuteStep(System.Web.HttpApplication+IExecutionStep step, System.Boolean& completedSynchronously)
curl --request GET 'https://website.com/page' \
--header 'Content-Length:514' \
--header 'Accept-Language:zh;q=0.9,en;q=0.8' \
--header 'Accept-Encoding:gzip, deflate' \
--header 'Host:website.com' \
--header 'Accept:text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1' \
--header 'User-Agent:Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)' \
--header 'Connection:close' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--header 'Refer:http://website.com/' \
--data '?(?���?P
H?;j????�ÖjuC??=?zh-z???�??e?�??l????�?�y?d??$?��?????|?�??q�????~}Z?3[g??9vn@S?�??n ??�??/a???8??e?
?
yJ��F
?t=??9??*?\�?(�D??�?�?Q�J????'

SqlDependency and MVC Donut Caching

Salut les Charentais et merci pour cette librairie qui met très utile. Je sais qu'on vous a déjà posé la question mais pensez vous gérer les dépendances SQL ou avez vous une solutions de remplacement ?

Je vous explique rapidement : j'ai développé une plateforme éditoriale multisite pour gérer nos sites éditoriaux.
J'ai absolument besoin d'avoir des block rotatifs pour les annonceurs et autres block autopromo donc la le donut caching fait le job. Par contre lorsque d'un journaliste publie ou modifie un article, je préfère utiliser la dépendance SQL car le cache doit être flushé sur 2 serveurs (load balanced) à chaque modification.

Merci
Cordialement
MENNA Stéphane

how to set duration programmatically

i want to change the duration of DonutOutputCache attribute from database record.

so i just write a custom outputcache which is childof DonutOutputCacheAttribute :
public class CmsOutputCache : DonutOutputCacheAttribute
{
public CmsOutputCache()
{
var setting = SettingBL.GetAdvancedSetting();
this.Duration = setting.TimeCache * 15;

    }
}

and use it like this :
[ChildActionOnly]
[CmsOutputCache]
public ActionResult HeaderSlider(){}

but the behavior of caching not working now!
how to set duration?

[Enhancement] Disable Donut Hole When User Not Logged In

I'm just doing some profiling on my code, and am wondering if it's possible to have Donut Hole caching disabled if User.Identity.IsAuthenticated = false?

My thinking is, if the user is not logged in, we simply serve from the cache immediately.

If a user is logged in, then we use the donut hole cache to fill in the user specific parts of the page - as it happens currently.

In terms of efficiency, it will surely be much faster to do it this way, than have several "Donut Holes", which check if a user is Logged in, and if not, put in the same standard code by replacement, into the output stream.

Ideally, I could create DonutHole Cache Categories, for example:

  1. Not Logged In / Logged In
  2. Is Mobile / Not Mobile User
  3. Is Internet Explorer 7 User / Not IE7 User

Then the cache would populate different versions for each type (and combination of type).

As we're using an output cache to try and improve efficiency, it seems sensible to take it a step further. What do you think? Or does this already exist and I've just missed it?

Sometimes the cached page becomes blank page.

I use mvcdonutcaching on one page of my site. It runs well except that sometimes the page becomes blank page, so that I must restart IIS to recover. the problem happens every a few days.

I wonder if this problem is related to mvcdonutcaching.

Thanks a lot!

Cache expiry policy

Hi

After a few quick tests, I believe the cache duration is fixed rather than sliding. Can you confirm this? Also, is there a way to change this policy through code?

help,if custom RouteConfig,the 'area' parameter not work in asp.net mvc

file:App_Start/RouteConfig.cs

namespace XXXXXXX
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.LowercaseUrls = true;
            routes.MapRoute(
               name: "Default",
               url: "{area}/{controller}/{action}/{id}",
                //defaults: new { controller = "Default", action = "Index", area = "000000", id = UrlParameter.Optional },
               defaults: new { controller = "Home", action = "Index", area = "000000", id = UrlParameter.Optional },
               constraints: new { area = @"\d{6}" }
            );
        }
    }
}

then

[DonutOutputCache(Duration = 300, VaryByCustom = "area")]
public ActionResult Index(int area)
{
    return View();
}

then

it is not work,how to do?

Intermittent Object reference not set to an instance of an object

I am seeing this quite often on one of my sites. Its a multi-store implementation, so multiple stores running on different urls all from a single app.

I get the following error intermittently, from once a day up to 4 or 5?

Server Error in '/' Application.
Object reference not set to an instance of an object.
Description: Object reference not set to an instance of an object. 

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error: 
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 
[NullReferenceException: Object reference not set to an instance of an object.]
   DevTrends.MvcDonutCaching.KeyGenerator.GenerateKey(ControllerContext context, CacheSettings cacheSettings) in c:\Users\moonpyk\Documents\Visual Studio 2012\Projects\mvcdonutcaching\DevTrends.MvcDonutCaching\KeyGenerator.cs:43
   DevTrends.MvcDonutCaching.DonutOutputCacheAttribute.ExecuteCallback(ControllerContext context, Boolean hasErrors) in c:\Users\moonpyk\Documents\Visual Studio 2012\Projects\mvcdonutcaching\DevTrends.MvcDonutCaching\DonutOutputCacheAttribute.cs:268
   System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList`1 filters, Exception exception) +169
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +727005
   System.Web.Mvc.Controller.ExecuteCore() +158
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +333
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +61
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +14
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +51
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +605
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +287

Missing null check in KeyGenerator.cs

Null check for DataTokensKeyArea is missing on line 63.

63 if (routeData.DataTokens.ContainsKey(DataTokensKeyArea))
64 {
65    areaName = routeData.DataTokens[DataTokensKeyArea].ToString();
66 }

This causes is to crash in some cases (example using it with surfacecontrollers in umbraco).

It looks like you check for null on routedata values, but not on the datatoken.

Regards
Martin

Nested Donut Caching

I don't think the donut cache is working for child actions.

Here is a simplified test case:

public ActionResult Test()
{
   return View();
}

[DonutOutputCache(Duration = 43200, VaryByParam = "*")]
public ActionResult TestChild()
{
    return View();
}

Test Action:

@{
    Layout = null;
}

@{ Html.RenderAction("TestChild"); }

The test child action has donut hole elements which work when called directly.

However, in this case (ie. calling Test()), the entire output of TestChild is cached, and on each subsequent call the first cached item is used. Hence, the donut holes created in TestChild are no longer computed.

Is there something wrong with this set up? Or is this not a scenario that is supported?

Thanks!
Daz.

Do you plan on supporting VaryByHeader

It would be real handy, as that is clutch for supporting different languages. I suppose I could implement VaryByCustom and look at the UI thread, but I'd prefer not to :)

How to remove Child action cache

I've searched for this but I can't find it. See here an example:

Index action of the HomeController (homepage):

[AllowAnonymous]
public ActionResult Index()
{
   return View();
}

ChildAction of the NewsController:

[AllowAnonymous]
[ChildActionOnly]
[DonutOutputCache(Duration = 600, Location = OutputCacheLocation.Server)]
public PartialViewResult LastArticles(int numberOfArticles)
{
    return PartialView("_LastArticles", db.NewsArticles
    .Include(i => i.Tags)
    .Include(i => i.SeoTags)
    .Where(n => n.Status == PublishStatus.Published)
    .OrderByDescending(n => n.PublishDate)
    .Take(numberOfArticles)
    .ToList());
}

Index view of the HomeController:

@{ Html.RenderAction("LastArticles", "News", new { numberOfArticles = 2 }); }

To clear the cache I have an Admin area in my application with a controller and action in it to update the data stored by the child action. So when a news article is updated. The cache should get refreshed on the homepage.

In that action I have the following code:

var cacheManager = new OutputCacheManager();
cacheManager.RemoveItem("News", "LastArticles", new { area = "", numberOfArticles = 2 });
cacheManager.RemoveItem("News", "LastArticles", new { area = "" });

I tried multiple versions but without luck. Can you help me?

Clear cache with return View doesn't work

I have

public class AssociationController: Controller
{
    public ActionResult Association(string nom_asso)
    {
        var model = getMyModel();
        if (model != null)
        {
            return View(model);
        }

        var model2 = getOtherModel();
        return View("AssociationCrawl", model2);
    }
}

If i want to remove cache when model is null with this:

var cacheManager = new OutputCacheManager();
cacheManager.RemoveItems("Association", "Association", new { nom_asso = nom_asso });

It's not working, so i can use this but it's not a good pratice because i remove all cached pages.

var cacheManager = new OutputCacheManager();
cacheManager.RemoveItems("Association", "Association");

DataContractSerializer seems is not respecting [EnumMember] attribute and causing errors with serializing view's RouteData.

Got this error:

Type 'PAM_Web.Views.People.ViewModels.PeopleViewMode' with data contract name 'PeopleViewMode:http://schemas.datacontract.org/2004/07/PAM_Web.Views.People.ViewModels' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Tracked it to the error on this line _serialiser.WriteObject(memoryStream, actionSettings):

    public string Serialise(ActionSettings actionSettings)
    {
        using (var memoryStream = new MemoryStream())
        {
           _serialiser.WriteObject(memoryStream, actionSettings);
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }

Seems that problem is that one of the route values i get at this point using String representation on the PAM_Web.Views.People.ViewModels.PeopleViewMode enum member. I have tried to decorate enum with [DataContact] and enum member with:

[EnumMember(Value = "0")]

doesn't work as well. I still get enum's member name here.

Found info here http://stackoverflow.com/questions/14391725/how-do-i-serialize-an-enum-value-as-a-string

"As seen in a number of other post, the .NET JsonSerializer or DataContractJsonSerializer don't respect the EnumMember attribute, but use the numeric value for the different members of the enumeration.
So writing your own custom serializer or use some 3rd party libraries are the way forward."

And suggesting to use Newtonsoft.Json. What do you think?

Thanks.

Is it safe to use OnResultExecuting and OnResultExecuted however I want?

An actionfilter has four hooks: OnActionExecuting, OnActionExecuted, OnResultExecuting, OnResultExecuted. I understand that this library uses the first two.

I need to use other actionfilters on my cached action. I usually use OnActionExecuting, but the action is cached so such an actionfilter won't be called. So instead I put such code in a donut hole (i.e. child view) and call it from a view. This works but is "messy" and harder to test.

So I've been trying to put this kind of stuff into actionfilters which use OnResultExecuting and OnResultExecuted. I noticed that it works most of the time as I expect.

What I need to know is this "safe" or will I break something? Can I do whatever I want in these two functions? Including changing headers, setting cookies, redirecting, etc.? I assume the only thing I can't do is change the cached result, but everything else is ok?

Clear Cache For GetVaryByCustomString - CacheProfile?

How do I clear the cache for pages that are using a custom string? I assumed you'd have something like

cacheManager.RemoveItemByCustomString("MyStringForSpecificPage");

or

cacheManager.RemoveItemByCacheProfile("ProfileName","MyStringForSpecificPage");

I have tried the below, but it doesn't work. I'm guessing because I'm using a custom cache profile?

// Remove the individual product from the cache
cacheManager.RemoveItems("Catalog", "Product", new { productId = eventMessage.Entity.Id});

Not working with route attribute

i have following route attributes

[Route("topics/{character}/{slug}-names-p{page:int}")]
[Route("topics/{character}/{slug}-names")]

but it shows the page 2 as empty. if i remove the route for paging. then the url is ?page=2, it works fine then.

It doesn't work with out query string parameter

Azure Redis output cache provider issue

Hi,

I use the library in my ASP.NET MVC project, with Azure Redis output cache provider from Microsoft, but there is exception if I use DonutOutputCache attribute. Seem like the library cannot create instance of the output cache provider.

image

My configuration is below. The configuration should have no problem because I use it with original OutputCache attribute and working fine

image

Handling Cookies

Firstly - MVC Donut Cache is excellent, thanks for releasing.

I'm having an issue understanding how cookies are meant to be handled with respect to the output cache.

Let's say I set a cookie in the method of a cached controller:

[DonutOutputCache(Duration = 43200, VaryByParam = "*")]
public ActionResult Index()
{
...
HttpCookie cookie = new HttpCookie("cookie");
cookie.Value = "cookieValue";
cookie.Expires = DateTime.Now.AddMonths(1);
cookie.Shareable = true;
Response.Cookies.Add(cookie);
...
Return View();
}

On the first load of this page, the cookie will be set. On all subsequent loads, it is not set.

Looking around a bit my understanding was setting cookie.Shareable to true would mean the cookie would be sent with all responses - is this not the case? Using DonutOutputCache, this setting appears to make no difference.

Do you have a different way to handle cookies in the response which works for all requests?

Thanks,
Daz.

Re-populate outputcache after app pool recycled

Scenario: New deploys, app pool naturally recycled, means the in-memory cache is lost and the first call to cached pages is slow.

Essentially, serving the cache from memory is going to be the quickest method, and so I want to stick with that. However, is there a way to save cache items to the DB, or external cache / filesystem / S3 (on a background thread), such that when the app is deployed / recycled, on startup, it pulls all the cache items into memory and there is no startup lag?

This seems like the optimal solution, rather than serve from a DB (slow), or external cache (also slow).

On a secondary, related note, when a cache item is evicted / timed out, are pages served from memory until a new, updated, cache item is created (ideally on a background thread)? This would cause similar timeout lag, but I haven't tested extensively enough to see if it's a reality, especially with the new deploy lag already in place.

I imagine this would work as such, timeout occurs, code checks if cache item was accessed within last 10% of timeout period, if so, updates cache with a fresh call to action (on background thread), whilst serving all follow up requests with cached version. Else, simply evicts cache item as normal. This would mean frequently accessed items were always served from the cache.

Would love your thoughts on the feasibility of above - or whether this functionality already exists?

FileResult getting corrupted

I'm using this package for the first time with Umbraco 7.3.1. The DonutOutputCache attribute is on a controller which is registered as the default controller in the application.

I also have a RenderMvcController which uses route hijacking to override the default controller and serve a file as a FileResult (normally a pdf). The problem I'm having is that the caching is still intercepting the request and causing all file downloads to get corrupted (I've tried multiple file types)

Is there any way to get the donuntcaching to ignore this controller entirely?

Thanks very much

Complex type as argument for Html.Action

My donut hole is a partial which I call like this:

@{
// create some data which is passed to the child action
var dict = new RouteValueDictionary();
dict.Add(MVC.Foo.BarParams.model, Model.DataExpectedByPartialView);
// invoke the child action
Html.RenderAction(
  MVC.Foo.Actions.ActionNames.Bar,
  MVC.Foo.Name,
  dict,
  excludeFromParentCache: true);
}

Standard stuff. As you can see my partial view needs some viewmodel data (which is not a primitive type), which I pass in. And that breaks the serializer.

Others have reported this problem as well. The suggestion there was to only use primitive types for such an argument. But I can't do that because that partial view (the donut hole) is a form which is expecting various viewmodel data.

How do I handle this problem?

excluding child action of a child action failes

Hi
I have a child action for creating my footer which loads data from database. And I am loading it like this in my Layout.chtml

@Html.Action("CreateFooter", "Home", true)

In CreateFooter action I call another child action for displaying page visit status which shouldn't be cached and needs to display fresh data. So in my CreateFooter.chtml

@Html.Action("GetStatus", "VisitCounter", new { Address = "PV-Home -> Index" },true)

But things in my footer gets messed up. some part of footer which is right after this line of code, repeats before whole footer!! If i change it to this line

@Html.Action("GetStatus", "VisitCounter", new { Address = "PV-Home -> Index" })

Nothing gets messed up but the visit status data wo'nt be fresh anymore.

In Home controller , CreateFooter has dounut attribute
In VisitCounter controller , GetStatus has'nt dounut attribute

Please kindly help me.

Exception Handling

Is it possible to cancel the request from being cached when an exception occurs?

Add Azure Caching Implementation

Allow the ability to use Azure Redis Caching along with MemoryCache.

Steps:

  1. Write interface around MemoryCacheProvider
  2. Write implementation that uses azure
  3. Put a switch in that allows the user to select Azure

DonutOutputCache VaryByCustom not working

Maybe anyone can help me find out what's going on here.
Steps to reproduce:

  • Create a domain and a sub domain pointing to the same ASP.NET MVC 4 application (example: localtest.me and sub.localtest.me)
    • Add the following method in global.asax file
        public override string GetVaryByCustomString(HttpContext context, string arg)
        {
            if (arg.ToLower() == "subdomain")
            {
                if (context.Request.Url.Host == "sub.localtest.me")
                    return "sub";
                else
                    return "main";
            }

            return base.GetVaryByCustomString(context, arg);
        }
  • Then decorate an action method with the following
[DonutOutputCache(Duration = 60, VaryByParam = "*", VaryByCustom = "subdomain")]
  • You can output just the current time in the view for example
<pre>@DateTime.UtcNow</pre>
  • Open the browser and start the main domain website page (eg: localtest.me), then open another browser with the sub domain website (eg: sub.localtest.me)

You'll see that the cache is preserved, while it should not.
Using:

[OutputCache(Duration = 60, VaryByParam = "*", VaryByCustom = "subdomain")]

Works correctly as expected (separated cache).

I've tried with both 1.2.3 and 1.3 release candidate with the same results.
Can you confirm it's a bug? It is really important for me to be fixed!

Filtering is not allowed. While implementing Donut Caching.

Hi, I am facing this problem while implementing Donut caching.
Filtering is not allowed. (System.Web.HttpResponse.set_Filter)
Stack Trace:

at System.Web.HttpResponse.set_Filter(Stream value)
at Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.PageInspectorHttpModule.OnPostRequestHandlerExecute(Object sender, EventArgs e)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)..

If I use Debug= false then I don't get any issue but get a blank page. Any help highly appreciated.

Sometimes application cache throws System.Web.HttpException

And application just return white blank page.
Here is full text of exception:

System.Web.HttpException (0x80004005): Filtering is not allowed.\r\n at System.Web.HttpResponse.set_Filter(Stream value)\r\n at Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.ArteryFilter.InstallOnResponse(HttpResponse response)\r\n at Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.PageInspectorHttpModule.OnPostRequestHandlerExecute(Object sender, EventArgs e)\r\n at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()\r\n at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

and here is TargetSite form exception

{Void set_Filter(System.IO.Stream)}
Attributes: Public | HideBySig | SpecialName
CallingConvention: Standard | HasThis
ContainsGenericParameters: false
CustomAttributes: Count = 0
DeclaringType: {Name = "HttpResponse" FullName = "System.Web.HttpResponse"}
IsAbstract: false
IsAssembly: false
IsConstructor: false
IsFamily: false
IsFamilyAndAssembly: false
IsFamilyOrAssembly: false
IsFinal: false
IsGenericMethod: false
IsGenericMethodDefinition: false
IsHideBySig: true
IsPrivate: false
IsPublic: true
IsSecurityCritical: true
IsSecuritySafeCritical: true
IsSecurityTransparent: false
IsSpecialName: true
IsStatic: false
IsVirtual: false
MemberType: Method
MetadataToken: 100666196
MethodHandle: {System.RuntimeMethodHandle}
MethodImplementationFlags: IL
Module: {System.Web.dll}
Name: "set_Filter"
ReflectedType: {Name = "HttpResponse" FullName = "System.Web.HttpResponse"}
ReturnParameter: {Void }
ReturnType: {Name = "Void" FullName = "System.Void"}
ReturnTypeCustomAttributes: {Void }

Custom output cache provider using MongoDb

Hi -

We are having an issue with using custom output cache provider where the output is returned correctly after the initial call, but the response lacks a content-type header, and renders as raw html in the browser

        // GET: /Home/
        //#if !DEBUG
            [DonutOutputCache(CacheProfile = "Long", VaryByCustom = "host;rawurl")]
        //#endif
        public ActionResult Index()
 public override object Add(string key, object entry, DateTime utcExpiry)
        {
            Debug.WriteLine("Cache.Add({0}, {1}, {2})", key, entry, utcExpiry);
            key = Md5(key);

            if (utcExpiry == DateTime.MaxValue)
                utcExpiry = DateTime.UtcNow.AddMinutes(5);

            var query = MongoDB.Driver.Builders.Query.EQ("_id", key);

            var cacheItem = _cacheItems.FindOneAs<CacheItem>(query);

            if (cacheItem != null)
            {
                if (cacheItem.Expiration.ToUniversalTime() <= DateTime.UtcNow)
                {
                    _cacheItems.Remove(query);
                }
                else
                {
                    return Deserialize(cacheItem.Item);
                }
            }
            _cacheItems.Insert(new CacheItem
            {
                Id = key,
                Item = Serialize(entry),
                Expiration = utcExpiry
            });
            return entry;
        }

The entry is returned after Adding, but the raw html is rendered in the browser. Second request uses Get to retrieve the item from the output cache and the output renders correctly.

First request response headers:

Cache-Control:private
Date:Tue, 27 Jan 2015 09:19:38 GMT
Server:Microsoft-IIS/8.5
Transfer-Encoding:chunked
X-AspNet-Version:4.0.30319

Second request response headers:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: -1
Vary: Accept-Encoding
Glimpse-RequestID: 8fbff9ba-5bf1-470a-8dd5-a005ca3d12b9
Date: Tue, 27 Jan 2015 09:10:31 GMT
Content-Length: 10187

Child actions are not allowed to perform redirect actions.

Sometimes, I don't know why, I got error "Child actions are not allowed to perform redirect actions." error message. This error comes from ˙@Html.Action("CookieLaw", "Home", true)˙ and CookieLaw action contains just one line:

public ActionResult CookieLaw()
{
    return PartialView();
}

and View for this action:

@if (ViewBag.IsCookieLawConfirmed == null || !(bool)ViewBag.IsCookieLawConfirmed)
{
    <script type="text/javascript">
        var CasinoLaw = function () {
            // public
            this.HideCookieLaw = function () {
                document.getElementById("casino-cookie-law").className += " hide";
                SetCookie("@Apollo.Casino.Frontend.Features.Attributes.CookieLawAttribute.COOKIE_LAW", 1, 3650);
            };
            // private
            var SetCookie = function (cookieName, cookieValue, nDays) {
                var today = new Date();
                var expire = new Date();
                if (nDays == null || nDays == 0) nDays = 1;
                expire.setTime(today.getTime() + 3600000 * 24 * nDays);
                document.cookie = cookieName + "=" + escape(cookieValue) + ";expires=" + expire.toGMTString() + ";path=/";
            };
        };
    </script>

    <div id="casino-cookie-law" class="cookie-law">
        <div class="wrapper">
            <button type="button" onclick="javascript: var c = new CasinoLaw(); c.HideCookieLaw();">OK</button>
            <p>@PortalInfo.GetText("Casino.CookieLawPolicy.Text")</p>
        </div>
    </div>
}

So, I'm not using redirect. Please tell me what information can I provide to help to investigate this issue...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.