From 58317b18ce258849e49940d849ff161c5ce523ea Mon Sep 17 00:00:00 2001 From: twirpx Date: Tue, 28 Mar 2017 00:45:22 +0500 Subject: [PATCH] Fixing NRE when CacheTagHelper throws and exception (#5989) Fixes #5988 --- .../CacheTagHelper.cs | 3 +- .../CacheTagHelperTest.cs | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/CacheTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/CacheTagHelper.cs index 0e2224f541..67cd43c351 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/CacheTagHelper.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/CacheTagHelper.cs @@ -104,10 +104,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers // such that the tokens are inherited. result = ProcessContentAsync(output); - content = await result; entry.SetOptions(options); entry.Value = result; + + content = await result; } } catch diff --git a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/CacheTagHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/CacheTagHelperTest.cs index 7d924ed536..af1a97409e 100644 --- a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/CacheTagHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/CacheTagHelperTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text.Encodings.Web; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Html; @@ -647,6 +648,100 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers Assert.Equal(2, calls); } + + + [Fact] + public async Task ProcessAsync_ExceptionInProcessing_DoNotThrowInSubsequentRequests() + { + // Arrange + var id = "unique-id"; + var childContent = "some-content"; + var cache = new MemoryCache(new MemoryCacheOptions()); + + var counter = 0; + + Task GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder) + { + counter++; + if (counter < 3) + { + // throw on first two calls + throw new Exception(); + } + else + { + // produce content on third call + var tagHelperContent = new DefaultTagHelperContent(); + tagHelperContent.SetHtmlContent(childContent); + return Task.FromResult(tagHelperContent); + } + } + + var tagHelperContext1 = GetTagHelperContext(id); + var tagHelperContext2 = GetTagHelperContext(id); + var tagHelperContext3 = GetTagHelperContext(id); + var tagHelperContext4 = GetTagHelperContext(id); + + var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync); + var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync); + var tagHelperOutput3 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync); + var tagHelperOutput4 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync); + + var cacheTagHelper = new CacheTagHelper(cache, new HtmlTestEncoder()) + { + ViewContext = GetViewContext(), + Enabled = true, + ExpiresAfter = TimeSpan.FromHours(1.0) + }; + + // Act - 1 + + await Assert.ThrowsAsync(() => cacheTagHelper.ProcessAsync(tagHelperContext1, tagHelperOutput1)); + + // Assert - 1 + + Assert.Equal(1, counter); + Assert.Empty(tagHelperOutput1.PreContent.GetContent()); + Assert.Empty(tagHelperOutput1.PostContent.GetContent()); + Assert.False(tagHelperOutput1.IsContentModified); + Assert.Empty(tagHelperOutput1.Content.GetContent()); + + // Act - 2 + + await Assert.ThrowsAsync(() => cacheTagHelper.ProcessAsync(tagHelperContext2, tagHelperOutput2)); + + // Assert - 2 + + Assert.Equal(2, counter); + Assert.Empty(tagHelperOutput2.PreContent.GetContent()); + Assert.Empty(tagHelperOutput2.PostContent.GetContent()); + Assert.False(tagHelperOutput2.IsContentModified); + Assert.Empty(tagHelperOutput2.Content.GetContent()); + + // Act - 3 + + await cacheTagHelper.ProcessAsync(tagHelperContext3, tagHelperOutput3); + + // Assert - 3 + + Assert.Equal(3, counter); + Assert.Empty(tagHelperOutput3.PreContent.GetContent()); + Assert.Empty(tagHelperOutput3.PostContent.GetContent()); + Assert.True(tagHelperOutput3.IsContentModified); + Assert.Equal(childContent, tagHelperOutput3.Content.GetContent()); + + // Act - 4 + + await cacheTagHelper.ProcessAsync(tagHelperContext4, tagHelperOutput4); + + // Assert - 4 + + Assert.Equal(3, counter); + Assert.Empty(tagHelperOutput4.PreContent.GetContent()); + Assert.Empty(tagHelperOutput4.PostContent.GetContent()); + Assert.True(tagHelperOutput4.IsContentModified); + Assert.Equal(childContent, tagHelperOutput4.Content.GetContent()); + } private static ViewContext GetViewContext() {