Skip to content

Commit a295b97

Browse files
author
DevTrends
committed
Major refactor. Added VaryByParam and VaryByCustom support.
1 parent 8d2ee9f commit a295b97

22 files changed

+670
-108
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.IO;
3+
using System.Web.Mvc;
4+
5+
namespace DevTrends.MvcDonutCaching
6+
{
7+
public class ActionOutputBuilder : IActionOutputBuilder
8+
{
9+
public string GetActionOutput(ViewResultBase viewResult, ActionExecutedContext filterContext)
10+
{
11+
var viewName = String.IsNullOrEmpty(viewResult.ViewName)
12+
? filterContext.RouteData.GetRequiredString("action")
13+
: viewResult.ViewName;
14+
15+
var fullViewResult = viewResult as ViewResult;
16+
17+
if (fullViewResult == null)
18+
{
19+
viewResult.View = ViewEngines.Engines.FindPartialView(filterContext, viewName).View;
20+
}
21+
else
22+
{
23+
viewResult.View = ViewEngines.Engines.FindView(filterContext, viewName, fullViewResult.MasterName).View;
24+
}
25+
26+
using (var stringWriter = new StringWriter())
27+
{
28+
var viewContext = new ViewContext(filterContext.Controller.ControllerContext, viewResult.View,
29+
viewResult.ViewData, viewResult.TempData, stringWriter);
30+
31+
viewResult.View.Render(viewContext, stringWriter);
32+
33+
return stringWriter.GetStringBuilder().ToString();
34+
}
35+
}
36+
}
37+
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
namespace DevTrends.MvcDonutCaching
1+
using System.Web.Routing;
2+
3+
namespace DevTrends.MvcDonutCaching
24
{
35
public class ActionSettings
46
{
57
public string ActionName { get; set; }
68
public string ControllerName { get; set; }
7-
public object RouteValues { get; set; }
9+
public RouteValueDictionary RouteValues { get; set; }
810
}
911
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.IO;
2+
using System.Runtime.Serialization;
3+
using System.Text;
4+
using System.Web.Routing;
5+
6+
namespace DevTrends.MvcDonutCaching
7+
{
8+
public class ActionSettingsSerialiser : IActionSettingsSerialiser
9+
{
10+
private readonly DataContractSerializer _serialiser;
11+
12+
public ActionSettingsSerialiser()
13+
{
14+
_serialiser = new DataContractSerializer(typeof(ActionSettings), new[] { typeof(RouteValueDictionary) });
15+
}
16+
17+
public string Serialise(ActionSettings actionSettings)
18+
{
19+
using (var memoryStream = new MemoryStream())
20+
{
21+
_serialiser.WriteObject(memoryStream, actionSettings);
22+
return Encoding.UTF8.GetString(memoryStream.ToArray());
23+
}
24+
}
25+
26+
public ActionSettings Deserialise(string serialisedActionSettings)
27+
{
28+
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(serialisedActionSettings)))
29+
{
30+
return (ActionSettings)_serialiser.ReadObject(memoryStream);
31+
}
32+
}
33+
}
34+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+

2+
namespace DevTrends.MvcDonutCaching
3+
{
4+
public class CacheSettings
5+
{
6+
public bool IsCachingEnabled { get; set; }
7+
public int Duration { get; set; }
8+
public string VaryByParam { get; set; }
9+
public string VaryByCustom { get; set; }
10+
}
11+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Configuration;
2+
using System.Web;
3+
using System.Web.Configuration;
4+
5+
namespace DevTrends.MvcDonutCaching
6+
{
7+
public class CacheSettingsManager : ICacheSettingsManager
8+
{
9+
private const string AspnetInternalProviderName = "AspNetInternalProvider";
10+
private readonly OutputCacheSection _outputCacheSection;
11+
12+
public CacheSettingsManager()
13+
{
14+
_outputCacheSection = (OutputCacheSection)ConfigurationManager.GetSection("system.web/caching/outputCache");
15+
}
16+
17+
public string RetrieveOutputCacheProviderType()
18+
{
19+
if (_outputCacheSection.DefaultProviderName == AspnetInternalProviderName)
20+
{
21+
return null;
22+
}
23+
else
24+
{
25+
return _outputCacheSection.Providers[_outputCacheSection.DefaultProviderName].Type;
26+
}
27+
}
28+
29+
public OutputCacheProfile RetrieveOutputCacheProfile(string cacheProfileName)
30+
{
31+
var outputCacheSettingsSection = (OutputCacheSettingsSection)ConfigurationManager.GetSection("system.web/caching/outputCacheSettings");
32+
33+
if (outputCacheSettingsSection != null && outputCacheSettingsSection.OutputCacheProfiles.Count > 0)
34+
{
35+
var cacheProfile = outputCacheSettingsSection.OutputCacheProfiles[cacheProfileName];
36+
37+
if (cacheProfile != null)
38+
{
39+
return cacheProfile;
40+
}
41+
}
42+
43+
throw new HttpException(string.Format("The '{0}' cache profile is not defined. Please define it in the configuration file.", cacheProfileName));
44+
}
45+
46+
public bool IsCachingEnabledGlobally
47+
{
48+
get { return _outputCacheSection.EnableOutputCache; }
49+
}
50+
}
51+
}

DevTrends.MvcDonutCaching/DevTrends.MvcDonutCaching.csproj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,38 @@
3535
<Reference Include="System.configuration" />
3636
<Reference Include="System.Core" />
3737
<Reference Include="System.Runtime.Caching" />
38+
<Reference Include="System.Runtime.Serialization" />
3839
<Reference Include="System.Web" />
3940
<Reference Include="System.Web.Extensions" />
4041
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
42+
<Reference Include="System.Web.Routing" />
4143
<Reference Include="System.Xml.Linq" />
4244
<Reference Include="System.Data.DataSetExtensions" />
4345
<Reference Include="Microsoft.CSharp" />
4446
<Reference Include="System.Data" />
4547
<Reference Include="System.Xml" />
4648
</ItemGroup>
4749
<ItemGroup>
50+
<Compile Include="ActionOutputBuilder.cs" />
4851
<Compile Include="ActionSettings.cs" />
52+
<Compile Include="ActionSettingsSerialiser.cs" />
53+
<Compile Include="CacheSettings.cs" />
54+
<Compile Include="CacheSettingsManager.cs" />
55+
<Compile Include="DonutHoleFiller.cs" />
56+
<Compile Include="IActionOutputBuilder.cs" />
57+
<Compile Include="IActionSettingsSerialiser.cs" />
58+
<Compile Include="ICacheSettingsManager.cs" />
59+
<Compile Include="IDonutHoleFiller.cs" />
60+
<Compile Include="IKeyGenerator.cs" />
61+
<Compile Include="IOutputCacheManager.cs" />
62+
<Compile Include="KeyGenerator.cs" />
4963
<Compile Include="DonutOutputCacheAttribute.cs" />
5064
<Compile Include="HtmlHelperExtensions.cs" />
65+
<Compile Include="IKeyBuilder.cs" />
66+
<Compile Include="KeyBuilder.cs" />
5167
<Compile Include="MemoryCacheProvider.cs" />
68+
<Compile Include="OutputCache.cs" />
69+
<Compile Include="OutputCacheManager.cs" />
5270
<Compile Include="Properties\AssemblyInfo.cs" />
5371
</ItemGroup>
5472
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.IO;
3+
using System.Text.RegularExpressions;
4+
using System.Web.Mvc;
5+
using System.Web.Mvc.Html;
6+
using System.Web.Routing;
7+
8+
namespace DevTrends.MvcDonutCaching
9+
{
10+
public class DonutHoleFiller : IDonutHoleFiller
11+
{
12+
private static readonly Regex DonutHoles = new Regex("<!--Donut#(.*)#-->", RegexOptions.Compiled);
13+
14+
private readonly IActionSettingsSerialiser _actionSettingsSerialiser;
15+
16+
public DonutHoleFiller(IActionSettingsSerialiser actionSettingsSerialiser)
17+
{
18+
if (actionSettingsSerialiser == null)
19+
{
20+
throw new ArgumentNullException("actionSettingsSerialiser");
21+
}
22+
23+
_actionSettingsSerialiser = actionSettingsSerialiser;
24+
}
25+
26+
public string ReplaceDonutHoleContent(string content, ControllerContext filterContext)
27+
{
28+
if (filterContext.IsChildAction)
29+
{
30+
return content;
31+
}
32+
33+
return DonutHoles.Replace(content, new MatchEvaluator(match =>
34+
{
35+
var actionSettings = _actionSettingsSerialiser.Deserialise(match.Groups[1].Value);
36+
37+
return InvokeAction(filterContext.Controller, actionSettings.ActionName, actionSettings.ControllerName, actionSettings.RouteValues);
38+
}));
39+
}
40+
41+
private static string InvokeAction(ControllerBase controller, string actionName, string controllerName, RouteValueDictionary routeValues)
42+
{
43+
var viewContext = new ViewContext(controller.ControllerContext, new WebFormView(controller.ControllerContext, "tmp"),
44+
controller.ViewData, controller.TempData, TextWriter.Null);
45+
46+
var htmlHelper = new HtmlHelper(viewContext, new ViewPage());
47+
48+
return htmlHelper.Action(actionName, controllerName, routeValues).ToString();
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)