示例#1
0
 /// <summary>
 /// Creates an instance of <see cref="CacheTagKey"/> for a specific <see cref="CacheTagHelper"/>.
 /// </summary>
 /// <param name="tagHelper">The <see cref="CacheTagHelper"/>.</param>
 /// <param name="context">The <see cref="TagHelperContext"/>.</param>
 /// <returns>A new <see cref="CacheTagKey"/>.</returns>
 public CacheTagKey(CacheTagHelper tagHelper, TagHelperContext context)
     : this(tagHelper)
 {
     Key     = context.UniqueId;
     _prefix = nameof(CacheTagHelper);
 }
示例#2
0
    public async Task ProcessAsync_ExceptionInProcessing_DoesntBlockConcurrentRequests()
    {
        // Arrange
        var id           = "unique-id";
        var childContent = "some-content";
        var event1       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
        var event2       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
        var event3       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
        var calls        = 0;
        var cache        = new MemoryCache(new MemoryCacheOptions());

        var tagHelperContext1 = GetTagHelperContext(id + 1);
        var tagHelperContext2 = GetTagHelperContext(id + 2);

        var tagHelperOutput1 = new TagHelperOutput(
            "cache",
            new TagHelperAttributeList(),
            getChildContentAsync: (useCachedResult, encoder) =>
        {
            calls++;
            event2.SetResult(0);

            throw new Exception();
        });

        var tagHelperOutput2 = new TagHelperOutput(
            "cache",
            new TagHelperAttributeList(),
            getChildContentAsync: async(useCachedResult, encoder) =>
        {
            calls++;
            await event3.Task.TimeoutAfter(TimeSpan.FromSeconds(5));

            var tagHelperContent = new DefaultTagHelperContent();
            tagHelperContent.SetHtmlContent(childContent);
            return(tagHelperContent);
        });

        var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
        {
            ViewContext = GetViewContext(),
            Enabled     = true
        };

        var cacheTagHelper2 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
        {
            ViewContext = GetViewContext(),
            Enabled     = true
        };

        // Act

        var task1 = Task.Run(async() =>
        {
            await event1.Task.TimeoutAfter(TimeSpan.FromSeconds(5));
            await Assert.ThrowsAsync <Exception>(() => cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1));
            event3.SetResult(0);
        });

        var task2 = Task.Run(async() =>
        {
            await event2.Task.TimeoutAfter(TimeSpan.FromSeconds(5));
            await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
        });

        event1.SetResult(0);
        await Task.WhenAll(task1, task2);

        // Assert
        Assert.Empty(tagHelperOutput1.PreContent.GetContent());
        Assert.Empty(tagHelperOutput1.PostContent.GetContent());
        Assert.False(tagHelperOutput1.IsContentModified);
        Assert.Empty(tagHelperOutput1.Content.GetContent());

        Assert.Empty(tagHelperOutput2.PreContent.GetContent());
        Assert.Empty(tagHelperOutput2.PostContent.GetContent());
        Assert.True(tagHelperOutput2.IsContentModified);
        Assert.Equal(childContent, tagHelperOutput2.Content.GetContent());

        Assert.Equal(2, calls);
    }
示例#3
0
    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 <TagHelperContent> 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>(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(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
        {
            ViewContext  = GetViewContext(),
            Enabled      = true,
            ExpiresAfter = TimeSpan.FromHours(1.0)
        };

        // Act - 1

        await Assert.ThrowsAsync <Exception>(() => 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 <Exception>(() => 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());
    }
示例#4
0
    public async Task ProcessAsync_FlowsEntryLinkThatAllowsAddingTriggersToAddedEntry()
    {
        // Arrange
        var id = "some-id";
        var expectedContent = new DefaultTagHelperContent();

        expectedContent.SetContent("some-content");
        var tokenSource = new CancellationTokenSource();
        var cache       = new MemoryCache(new MemoryCacheOptions()
        {
            TrackLinkedCacheEntries = true
        });
        var cacheEntryOptions = new MemoryCacheEntryOptions()
                                .AddExpirationToken(new CancellationChangeToken(tokenSource.Token));
        var tagHelperContext = new TagHelperContext(
            tagName: "cache",
            allAttributes: new TagHelperAttributeList(),
            items: new Dictionary <object, object>(),
            uniqueId: id);
        var tagHelperOutput = new TagHelperOutput(
            "cache",
            new TagHelperAttributeList {
            { "attr", "value" }
        },
            getChildContentAsync: (useCachedResult, encoder) =>
        {
            if (!cache.TryGetValue("key1", out TagHelperContent tagHelperContent))
            {
                tagHelperContent = expectedContent;
                cache.Set("key1", tagHelperContent, cacheEntryOptions);
            }

            return(Task.FromResult(tagHelperContent));
        });

        tagHelperOutput.PreContent.SetContent("<cache>");
        tagHelperOutput.PostContent.SetContent("</cache>");
        var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
        {
            ViewContext = GetViewContext(),
        };

        var cacheTagKey = new CacheTagKey(cacheTagHelper, tagHelperContext);
        var key         = cacheTagKey.GenerateKey();

        // Act - 1
        await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);

        var result = cache.TryGetValue(cacheTagKey, out Task <IHtmlContent> cachedValue);

        // Assert - 1
        Assert.Equal("HtmlEncode[[some-content]]", tagHelperOutput.Content.GetContent());
        Assert.True(result);

        // Act - 2
        tokenSource.Cancel();
        result = cache.TryGetValue(cacheTagKey, out cachedValue);

        // Assert - 2
        Assert.False(result);
        Assert.Null(cachedValue);
    }