From 079823c485426ed4fdb82243cd593fd7314439e9 Mon Sep 17 00:00:00 2001 From: Josh Berry Date: Fri, 13 Jan 2017 10:02:25 -0600 Subject: [PATCH] Output cache vary by query string modes (#7509) --- .../Controllers/AdminController.cs | 2 ++ .../Filters/OutputCacheFilter.cs | 11 ++++++++- .../Modules/Orchard.OutputCache/Migrations.cs | 23 ++++++++++++++++++- .../Models/CacheSettings.cs | 2 ++ .../Models/CacheSettingsPart.cs | 5 ++++ .../ViewModels/IndexViewModel.cs | 1 + .../Views/Admin/Index.cshtml | 16 ++++++++++--- 7 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs index 7ed0c5e44..027e42caf 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Controllers/AdminController.cs @@ -87,6 +87,7 @@ namespace Orchard.OutputCache.Controllers { DefaultCacheDuration = settings.DefaultCacheDuration, DefaultCacheGraceTime = settings.DefaultCacheGraceTime, DefaultMaxAge = settings.DefaultMaxAge, + VaryByQueryStringIsExclusive = settings.VaryByQueryStringIsExclusive, VaryByQueryStringParameters = settings.VaryByQueryStringParameters, VaryByRequestHeaders = settings.VaryByRequestHeaders, VaryByRequestCookies = settings.VaryByRequestCookies, @@ -115,6 +116,7 @@ namespace Orchard.OutputCache.Controllers { settings.DefaultCacheDuration = model.DefaultCacheDuration; settings.DefaultCacheGraceTime = model.DefaultCacheGraceTime; settings.DefaultMaxAge = model.DefaultMaxAge; + settings.VaryByQueryStringIsExclusive = model.VaryByQueryStringIsExclusive; settings.VaryByQueryStringParameters = model.VaryByQueryStringParameters; settings.VaryByRequestHeaders = model.VaryByRequestHeaders; settings.VaryByRequestCookies = model.VaryByRequestCookies; diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index 503fc0fdc..fab027621 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -388,8 +388,17 @@ namespace Orchard.OutputCache.Filters { // Vary by configured query string parameters. var queryString = filterContext.RequestContext.HttpContext.Request.QueryString; foreach (var key in queryString.AllKeys) { - if (key == null || (CacheSettings.VaryByQueryStringParameters != null && !CacheSettings.VaryByQueryStringParameters.Contains(key))) + if (key == null) continue; + + // In exclusive mode, don't vary if the key matches + if (CacheSettings.VaryByQueryStringIsExclusive && (CacheSettings.VaryByQueryStringParameters != null && CacheSettings.VaryByQueryStringParameters.Contains(key))) + continue; + + // In inclusive mode, don't vary if the key doesn't match + if(!CacheSettings.VaryByQueryStringIsExclusive && (CacheSettings.VaryByQueryStringParameters == null || !CacheSettings.VaryByQueryStringParameters.Contains(key))) + continue; + result[key] = queryString[key]; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Migrations.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Migrations.cs index 8bbce87a0..489eb2183 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Migrations.cs @@ -1,7 +1,16 @@ -using Orchard.Data.Migration; +using Orchard.ContentManagement; +using Orchard.Data.Migration; +using Orchard.OutputCache.Models; namespace Orchard.OutputCache { public class Migrations : DataMigrationImpl { + + private readonly IOrchardServices _orchardServices; + + public Migrations(IOrchardServices orchardServices) { + _orchardServices = orchardServices; + } + public int Create() { SchemaBuilder.CreateTable("CacheParameterRecord", @@ -56,5 +65,17 @@ namespace Orchard.OutputCache { return 7; } + + public int UpdateFrom7() { + var cacheSettings = _orchardServices.WorkContext.CurrentSite.As(); + if (!string.IsNullOrWhiteSpace(cacheSettings.VaryByQueryStringParameters)) { + // Prevent behavior from changing if vary on querystring was used prior to introduction of exclusive mode + cacheSettings.VaryByQueryStringIsExclusive = false; + } + else { + cacheSettings.VaryByQueryStringIsExclusive = true; // Default mode + }; + return 8; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs index 7797d7382..eee2f0892 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettings.cs @@ -11,6 +11,7 @@ namespace Orchard.OutputCache.Models { DefaultCacheDuration = part.DefaultCacheDuration; DefaultCacheGraceTime = part.DefaultCacheGraceTime; DefaultMaxAge = part.DefaultMaxAge; + VaryByQueryStringIsExclusive = part.VaryByQueryStringIsExclusive; VaryByQueryStringParameters = String.IsNullOrWhiteSpace(part.VaryByQueryStringParameters) ? null : part.VaryByQueryStringParameters.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray(); VaryByRequestHeaders = String.IsNullOrWhiteSpace(part.VaryByRequestHeaders) ? new HashSet() : new HashSet(part.VaryByRequestHeaders.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray()); VaryByRequestHeaders.Add("HOST"); // Always vary by host name/tenant. @@ -26,6 +27,7 @@ namespace Orchard.OutputCache.Models { public int DefaultCacheDuration { get; private set; } public int DefaultCacheGraceTime { get; private set; } public int DefaultMaxAge { get; private set; } + public bool VaryByQueryStringIsExclusive { get; private set; } public IEnumerable VaryByQueryStringParameters { get; private set; } public ISet VaryByRequestHeaders { get; private set; } public ISet VaryByRequestCookies { get; private set; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs index 69e8441fd..e884e1a7e 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Models/CacheSettingsPart.cs @@ -18,6 +18,11 @@ namespace Orchard.OutputCache.Models { set { this.Store(x => x.DefaultMaxAge, value); } } + public bool VaryByQueryStringIsExclusive { + get { return this.Retrieve(x => x.VaryByQueryStringIsExclusive); } + set { this.Store(x => x.VaryByQueryStringIsExclusive, value); } + } + public string VaryByQueryStringParameters { get { return this.Retrieve( diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs index b79ff5509..d5361b3cc 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/ViewModels/IndexViewModel.cs @@ -9,6 +9,7 @@ namespace Orchard.OutputCache.ViewModels { [Range(0, Int32.MaxValue), Required] public int DefaultCacheDuration { get; set; } [Range(0, Int32.MaxValue), Required] public int DefaultCacheGraceTime { get; set; } [Range(0, Int32.MaxValue), Required] public int DefaultMaxAge { get; set; } + public bool VaryByQueryStringIsExclusive { get; set; } public string VaryByQueryStringParameters { get; set; } public string VaryByRequestHeaders { get; set; } public string VaryByRequestCookies { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml index 161f1a54c..33693b1fe 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Views/Admin/Index.cshtml @@ -37,10 +37,20 @@
- @Html.TextBoxFor(m => m.VaryByQueryStringParameters, new { @class = "text medium" }) - @T("When defined, using comma separated values, sets caching to vary by the specified query string parameters. Leave empty to vary by all query string parameters.") +
+ @Html.RadioButtonFor(m => m.VaryByQueryStringIsExclusive, "False", new { Id = "varyByQueryStringExclusiveMode" }) + +
+
+ @Html.RadioButtonFor(m => m.VaryByQueryStringIsExclusive, "True", new { Id = "varyByQueryStringInclusiveMode" }) + +
+
+ @Html.TextBoxFor(m => m.VaryByQueryStringParameters, new { @class = "text medium" }) + @T("Separate multiple query string parameters with a comma.") +
- +
@Html.TextBoxFor(m => m.VaryByRequestHeaders, new { @class = "text medium" })