2

I'm doing donut caching with the MVCDonutCaching library.

Background to donut caching using this library:
The way it works, is you can cache a view, but exclude part of it from being cached, i.e. the "donut hole". You do this by having the uncachable stuff as a partial view, which is rendered by a child action. Then in the view you call that child action Html.RenderAction(.... This way everything but that child action will be cached.

Problem:
I need to cache a view, which contains a form. Problem is the form includes an AntiForgeryToken, which obviously should not be cached.

An obvious solution is to make that form a "donut hole", and render it via a child action. But, it needs complex viewmodel data, and child actions ony accept primitive types as arguments, otherwise I get serialization errors.

What is a good way around this?

h bob
  • 3,610
  • 3
  • 35
  • 51
  • One way is to create the form's viewmodel in the child action. But I don't like this option, as the form requires a lot of data to be fetched, and so I want it cached with the rest of the view. – h bob May 21 '15 at 15:27

1 Answers1

2

Found a way. Not sure if it's optimal, but it works.

Instead of making the form the "donut hole", I make the anti forgery token itself the donut hole.

[ChildActionOnly]                
public virtual ContentResult GetAntiForgeryToken() {
  using (var viewPage = new ViewPage()) {
    var htmlHelper = new HtmlHelper(new ViewContext(), viewPage);
    var token = htmlHelper.AntiForgeryToken();
    return Content(token.ToHtmlString());
  }
}

This requires creation of a dummy HtmlHelper, and then manually creating the token.

h bob
  • 3,610
  • 3
  • 35
  • 51