Dispose CancellationTokenSource created in CacheTagHelper (#6293)
Fixes #5649
This commit is contained in:
parent
ca751c5297
commit
13e76c24d3
|
|
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// The entry is set instead of assigning a value to the
|
// The entry is set instead of assigning a value to the
|
||||||
// task so that the expiration options are are not impacted
|
// task so that the expiration options are not impacted
|
||||||
// by the time it took to compute it.
|
// by the time it took to compute it.
|
||||||
|
|
||||||
using (var entry = MemoryCache.CreateEntry(cacheKey))
|
using (var entry = MemoryCache.CreateEntry(cacheKey))
|
||||||
|
|
@ -108,18 +108,24 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
||||||
content = await result;
|
content = await result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcs.SetResult(content);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// Remove the worker task from the cache in case it can't complete.
|
// Remove the worker task from the cache in case it can't complete.
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
|
|
||||||
|
// If an exception occurs, ensure the other awaiters
|
||||||
|
// render the output by themselves.
|
||||||
|
tcs.SetResult(null);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// If an exception occurs, ensure the other awaiters
|
// The tokenSource needs to be disposed as the MemoryCache
|
||||||
// render the output by themselves.
|
// will register a callback on the Token.
|
||||||
tcs.SetResult(null);
|
tokenSource.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -238,4 +244,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,4 +105,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -648,7 +648,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
||||||
Assert.Equal(2, calls);
|
Assert.Equal(2, calls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ProcessAsync_ExceptionInProcessing_DoNotThrowInSubsequentRequests()
|
public async Task ProcessAsync_ExceptionInProcessing_DoNotThrowInSubsequentRequests()
|
||||||
|
|
@ -743,15 +742,63 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
Assert.Equal(childContent, tagHelperOutput4.Content.GetContent());
|
Assert.Equal(childContent, tagHelperOutput4.Content.GetContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ProcessAsync_WorksForNestedCacheTagHelpers()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "Hello world";
|
||||||
|
var cache = new MemoryCache(new MemoryCacheOptions());
|
||||||
|
var encoder = new HtmlTestEncoder();
|
||||||
|
var cacheTagHelper1 = new CacheTagHelper(cache, encoder)
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
Enabled = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var cacheTagHelper2 = new CacheTagHelper(cache, encoder)
|
||||||
|
{
|
||||||
|
ViewContext = GetViewContext(),
|
||||||
|
Enabled = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var tagHelperOutput2 = new TagHelperOutput(
|
||||||
|
"cache",
|
||||||
|
new TagHelperAttributeList(),
|
||||||
|
getChildContentAsync: (useCachedResult, _) =>
|
||||||
|
{
|
||||||
|
var content = new DefaultTagHelperContent();
|
||||||
|
content.SetContent(expected);
|
||||||
|
return Task.FromResult<TagHelperContent>(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
var tagHelperOutput1 = new TagHelperOutput(
|
||||||
|
"cache",
|
||||||
|
new TagHelperAttributeList(),
|
||||||
|
getChildContentAsync: async (useCachedResult, _) =>
|
||||||
|
{
|
||||||
|
var context = GetTagHelperContext("test2");
|
||||||
|
var output = tagHelperOutput2;
|
||||||
|
await cacheTagHelper2.ProcessAsync(context, output);
|
||||||
|
return await output.GetChildContentAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await cacheTagHelper1.ProcessAsync(GetTagHelperContext(), tagHelperOutput1);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(encoder.Encode(expected), tagHelperOutput1.Content.GetContent());
|
||||||
|
}
|
||||||
|
|
||||||
private static ViewContext GetViewContext()
|
private static ViewContext GetViewContext()
|
||||||
{
|
{
|
||||||
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||||
return new ViewContext(actionContext,
|
return new ViewContext(
|
||||||
Mock.Of<IView>(),
|
actionContext,
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
Mock.Of<IView>(),
|
||||||
Mock.Of<ITempDataDictionary>(),
|
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
||||||
TextWriter.Null,
|
Mock.Of<ITempDataDictionary>(),
|
||||||
new HtmlHelperOptions());
|
TextWriter.Null,
|
||||||
|
new HtmlHelperOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TagHelperContext GetTagHelperContext(string id = "testid")
|
private static TagHelperContext GetTagHelperContext(string id = "testid")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue