#2142: Introducing enabled attribute for CacheTagHelper.
This commit is contained in:
parent
43e24b2aad
commit
b08a2154c1
|
|
@ -33,6 +33,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
private const string ExpiresSlidingAttributeName = "expires-sliding";
|
||||
private const string CachePriorityAttributeName = "priority";
|
||||
private const string CacheKeyTokenSeparator = "||";
|
||||
private const string EnabledAttributeName = "enabled";
|
||||
private static readonly char[] AttributeSeparator = new[] { ',' };
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -108,31 +109,48 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
[HtmlAttributeName(CachePriorityAttributeName)]
|
||||
public CachePreservationPriority? Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value which determines if the tag helper is enabled or not.
|
||||
/// </summary>
|
||||
[HtmlAttributeName(EnabledAttributeName)]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
var key = GenerateKey(context);
|
||||
TagHelperContent result;
|
||||
if (!MemoryCache.TryGetValue(key, out result))
|
||||
TagHelperContent result = null;
|
||||
if (Enabled)
|
||||
{
|
||||
// Create an EntryLink and flow it so that it is accessible via the ambient EntryLinkHelpers.ContentLink
|
||||
// for user code.
|
||||
var entryLink = new EntryLink();
|
||||
using (entryLink.FlowContext())
|
||||
var key = GenerateKey(context);
|
||||
if (!MemoryCache.TryGetValue(key, out result))
|
||||
{
|
||||
result = await context.GetChildContentAsync();
|
||||
}
|
||||
// Create an EntryLink and flow it so that it is accessible via the ambient
|
||||
// EntryLinkHelpers.ContextLink for user code.
|
||||
var entryLink = new EntryLink();
|
||||
using (entryLink.FlowContext())
|
||||
{
|
||||
result = await context.GetChildContentAsync();
|
||||
}
|
||||
|
||||
MemoryCache.Set(key, cacheSetContext =>
|
||||
{
|
||||
UpdateCacheContext(cacheSetContext, entryLink);
|
||||
return result;
|
||||
});
|
||||
MemoryCache.Set(key, cacheSetContext =>
|
||||
{
|
||||
UpdateCacheContext(cacheSetContext, entryLink);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the contents of the "cache" element since we don't want to render it.
|
||||
output.SuppressOutput();
|
||||
output.Content.SetContent(result);
|
||||
if (Enabled)
|
||||
{
|
||||
output.Content.SetContent(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await context.GetChildContentAsync();
|
||||
output.Content.SetContent(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Internal for unit testing
|
||||
|
|
|
|||
|
|
@ -228,6 +228,30 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Equal(expected2, response2.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CacheTagHelper_Activated_BasedOnEnabledParameter()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
|
||||
var client = server.CreateClient();
|
||||
client.BaseAddress = new Uri("http://localhost");
|
||||
|
||||
// Act
|
||||
// This is cached for 1s.
|
||||
var response1 = await client.GetStringAsync("/catalog/31");
|
||||
var response2 = await client.GetStringAsync("/catalog/32");
|
||||
|
||||
// This request is made before the cache expires with enabled set to false.
|
||||
client.DefaultRequestHeaders.Remove("IsCacheEnabled");
|
||||
client.DefaultRequestHeaders.Add("IsCacheEnabled", "false");
|
||||
var response3 = await client.GetStringAsync("/catalog/156");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Cached content for 31", response1.Trim());
|
||||
Assert.Equal("Cached content for 31", response2.Trim());
|
||||
Assert.Equal("Cached content for 156", response3.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CacheTagHelper_UsesVaryByCookie_ToVaryContent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -236,6 +236,89 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
Assert.Equal(expected, key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_DoesNotCache_IfDisabled()
|
||||
{
|
||||
// Arrange
|
||||
var id = "unique-id";
|
||||
var childContent = "original-child-content";
|
||||
var cache = new Mock<IMemoryCache>();
|
||||
cache.CallBase = true;
|
||||
cache.Setup(c => c.Set(
|
||||
/*key*/ It.IsAny<string>(),
|
||||
/*link*/ It.IsAny<IEntryLink>(),
|
||||
/*state*/ It.IsAny<object>(),
|
||||
/*create*/ It.IsAny<Func<ICacheSetContext, object>>()))
|
||||
.Returns(new DefaultTagHelperContent().SetContent("ok"))
|
||||
.Verifiable();
|
||||
object cacheResult;
|
||||
cache.Setup(c => c.TryGetValue(It.IsAny<string>(), It.IsAny<IEntryLink>(), out cacheResult))
|
||||
.Returns(false);
|
||||
var tagHelperContext = GetTagHelperContext(id, childContent);
|
||||
var tagHelperOutput = new TagHelperOutput("cache", new Dictionary<string, object>());
|
||||
var cacheTagHelper = new CacheTagHelper
|
||||
{
|
||||
ViewContext = GetViewContext(),
|
||||
MemoryCache = cache.Object,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
// Act
|
||||
await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(childContent, tagHelperOutput.Content.GetContent());
|
||||
cache.Verify(c => c.Set(
|
||||
/*key*/ It.IsAny<string>(),
|
||||
/*link*/ It.IsAny<IEntryLink>(),
|
||||
/*state*/ It.IsAny<object>(),
|
||||
/*create*/ It.IsAny<Func<ICacheSetContext, object>>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_ReturnsCachedValue_IfEnabled()
|
||||
{
|
||||
// Arrange
|
||||
var id = "unique-id";
|
||||
var childContent = "original-child-content";
|
||||
var cache = new Mock<IMemoryCache>();
|
||||
cache.CallBase = true;
|
||||
cache.Setup(c => c.Set(
|
||||
/*key*/ It.IsAny<string>(),
|
||||
/*link*/ It.IsAny<IEntryLink>(),
|
||||
/*state*/ It.IsAny<object>(),
|
||||
/*create*/ It.IsAny<Func<ICacheSetContext, object>>()))
|
||||
.Returns(new DefaultTagHelperContent().SetContent("ok"))
|
||||
.Verifiable();
|
||||
object cacheResult;
|
||||
cache.Setup(c => c.TryGetValue(It.IsAny<string>(), It.IsAny<IEntryLink>(), out cacheResult))
|
||||
.Returns(false);
|
||||
var tagHelperContext = GetTagHelperContext(id, childContent);
|
||||
var tagHelperOutput = new TagHelperOutput("cache", new Dictionary<string, object>());
|
||||
var cacheTagHelper = new CacheTagHelper
|
||||
{
|
||||
ViewContext = GetViewContext(),
|
||||
MemoryCache = cache.Object,
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
// Act
|
||||
await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(tagHelperOutput.PreContent.GetContent());
|
||||
Assert.Empty(tagHelperOutput.PostContent.GetContent());
|
||||
Assert.True(tagHelperOutput.IsContentModified);
|
||||
Assert.Equal(childContent, tagHelperOutput.Content.GetContent());
|
||||
cache.Verify(c => c.Set(
|
||||
/*key*/ It.IsAny<string>(),
|
||||
/*link*/ It.IsAny<IEntryLink>(),
|
||||
/*state*/ It.IsAny<object>(),
|
||||
/*create*/ It.IsAny<Func<ICacheSetContext, object>>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_ReturnsCachedValue_IfVaryByParamIsUnchanged()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace MvcTagHelpersWebSite.Controllers
|
|||
public ProductsService ProductsService { get; set; }
|
||||
|
||||
[HttpGet("/catalog")]
|
||||
public ViewResult Splash(int categoryId, int correlationId, [FromHeader]string locale)
|
||||
public ViewResult Splash(int categoryId, int correlationId, [FromHeader] string locale)
|
||||
{
|
||||
var category = categoryId == 1 ? "Laptops" : "Phones";
|
||||
ViewData["Category"] = category;
|
||||
|
|
@ -23,8 +23,15 @@ namespace MvcTagHelpersWebSite.Controllers
|
|||
}
|
||||
|
||||
[HttpGet("/catalog/{id:int}")]
|
||||
public ViewResult Details(int id)
|
||||
public ViewResult Details(int id, [FromHeader] string isCacheEnabled)
|
||||
{
|
||||
bool cacheEnabledHeader = true;
|
||||
if (!string.IsNullOrEmpty(isCacheEnabled))
|
||||
{
|
||||
bool.TryParse(isCacheEnabled, out cacheEnabledHeader);
|
||||
}
|
||||
|
||||
ViewBag.IsCacheEnabled = cacheEnabledHeader;
|
||||
ViewData["ProductId"] = id;
|
||||
return View();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@using Microsoft.Framework.Caching.Memory
|
||||
<cache expires-after="TimeSpan.FromSeconds(1)" priority="CachePreservationPriority.Low">
|
||||
<cache expires-after="TimeSpan.FromSeconds(1)" priority="CachePreservationPriority.Low" enabled="ViewBag.IsCacheEnabled">
|
||||
Cached content for @ViewBag.ProductId
|
||||
</cache>
|
||||
|
|
|
|||
Loading…
Reference in New Issue