Open Source

What's New In MvcDonutCaching 1.1?

A new version of MvcDonutCaching has just been released with even more features plus several bug fixes. Following user feedback, this release centres on allowing MvcDonutCaching to be used in place of the built-in OutputCache attribute in many common scenarios. This should mean that you can take advantage of the many MvcDonutCaching benefits without losing core OutputCache functionality. V1.1 adds support for non-view action results and cache location specification and also fixes several known bugs.

The MvcDonutCaching NuGet package was initially released to provide donut caching capabilities to ASP.NET MVC 3 - something that is not possible with the built-in OutputCache. Whilst this was the primary feature of the product, we also added a number of other improvements, particularly around invalidating existing cache items - something that was previously rather awkward. Surprisingly (for us), many people started using the package exclusively for these secondary features and not just when donut caching was required.

The key features that have been added in this release are:

Support for non-view ActionResults

The previous version of MvcDonutCaching allowed you to cache Views and PartialViews which is fine if we use the package exclusively for donut caching scenarios but not so useful if we want a general purpose OutputCache replacement.

This release has been refactored to allow more support for different action results. All text based file types (e.g. HTML, XML, JS, JSON, RSS...) should now work. I will look into supporting binary files for the next release if there is enough demand.

[DonutOutputCache(Duration = 10)]
public ActionResult JavaScriptTest()
    var message = string.Concat("hello from cached @", DateTime.Now.ToLongTimeString());

    return JavaScript("alert('" + message + "');");

[DonutOutputCache(Duration = 10)]
public ActionResult JsonTest()
    var obj = new
        This = "hello from cached @" + DateTime.Now.ToLongTimeString(),
        That = 42

    return Json(obj, JsonRequestBehavior.AllowGet);

[DonutOutputCache(Duration = 10)]
public ActionResult XmlTest()
    var xml = new XDocument(
      new XElement("test",
      new XElement("foo",
      new XAttribute("time", DateTime.Now.ToLongTimeString()),
      new XElement("bar", "1"),
      new XElement("bar", "2"),
      new XElement("bar", "3"))));

    return Content(xml.ToString(), "text/xml");

Ability to use the cache location enumeration

The built-in OutputCache allows you to control caching beyond the server. The OutputCacheLocation enumeration allows you to specify how the client and intermediate proxy servers handle the content. You can now specify a location value for your DonutOutputCache attributes, though you should be aware of how this may affect other MvcDonutCaching features.

Caching on the server (and nowhere else) is the default option. This gives you the greatest control, allowing you to take advantage of donut caching and enabling you to remove an item from the cache at any point. Once you allow a client or proxy server to cache content, you lose some of this control but depending on your situation, this may be acceptable. If you use donut caching with client caching, the donut hole will only be refreshed for new users visiting the page or if you force a page refresh with CTRL F5. Similarly, if you remove a page from the cache using the OutputCacheManager, it will only be removed from the server cache. Existing clients will continue to use any cached pages until they expires (or until the user forces a refresh). This is all fairly obvious - you cannot remove browser cache items from the server, but it is worth mentioning nevertheless.

[DonutOutputCache(Duration = 600, Location = OutputCacheLocation.ServerAndClient)]

Using the Html.Action overload in Layout Pages

You can now use the excludeFromParentCache=true Html.Action overloads without using the DonutOutputCache attribute on the controller action. Why is this useful? Several people pointed out that you might want to render an action from a layout page. In these cases, you may have some pages that use the layout and need to be cached and others that don't need to be cached. If you want the layout action to be a donut hole and get updated on every request, you will need to use the excludeFromParentCache=true Html.Action overload but in previous version of MvcDonutCaching, this caused a problem with non-cached pages - the action was not rendered. This has now been addressed and the action will be rendered in all cases.

As I explained in the first post on MvcDonutCaching, the Html.Action overload renders an HTML comment containing serialised details about the action. This is necessary to allow the action to be updated whenever the view is retrieved from the cache - i.e. to enable the donut caching. Normally the DonutOutputCache attribute removes the comment before the view output is returned to the client, but in this new scenario, there isn't necessarily a DonutOutputCache on the action, so the comment will not always be removed. Exposing internal information about an action (controller name, action name and route values) within the outputted HTML is not acceptable, so we now encrypt this information by default.


MvcDonutCaching 1.1 introduces a number of new features and bug fixes and it is strongly recommended that you update as soon as possible. Whilst version 1.0 primarily dealt with the ability to perform donut caching, the additional benefits that we added made it a popular choice as a general OutputCache replacement. Version 1.1 addresses some of the shortcomings of the previous version in this regard. As always, please report any bugs on CodePlex

Useful or Interesting?

If you liked the article, we would really appreciate it if you would share it with your Twitter followers.

Share on Twitter »


Comments are now closed for this article.