Esempio n. 1
0
        public void BasicWrites()
        {
            using (var writer = new ZStringWriter())
            {
                writer.Write("text1".AsSpan());
                writer.Write("text2");
                writer.Write('c');
                writer.Write(true);
                writer.Write(123);
                writer.Write(456f);
                writer.Write(789d);
                writer.Write("end".AsMemory());
                writer.WriteLine();

                var expected = "text1text2cTrue123456789end" + Environment.NewLine;
                Assert.Equal(expected, writer.ToString());
            }
        }
        public async Task <IHtmlContent> ProcessContentAsync(TagHelperOutput output, CacheContext cacheContext)
        {
            IHtmlContent content = null;

            while (content == null)
            {
                Task <IHtmlContent> result;

                // Is there any request already processing the value?
                if (!_dynamicCacheTagHelperService.Workers.TryGetValue(CacheId, out result))
                {
                    // There is a small race condition here between TryGetValue and TryAdd that might cause the
                    // content to be computed more than once. We don't care about this race as the probability of
                    // happening is very small and the impact is not critical.
                    var tcs = new TaskCompletionSource <IHtmlContent>();

                    _dynamicCacheTagHelperService.Workers.TryAdd(CacheId, tcs.Task);

                    try
                    {
                        var value = await _dynamicCacheService.GetCachedValueAsync(cacheContext);

                        if (value == null)
                        {
                            // The value is not cached, we need to render the tag helper output
                            var processedContent = await output.GetChildContentAsync();

                            using var writer = new ZStringWriter();
                            // Write the start of a cache debug block.
                            if (_cacheOptions.DebugMode)
                            {
                                // No need to optimize this code as it will be used for debugging purpose.
                                writer.WriteLine();
                                writer.WriteLine($"<!-- CACHE BLOCK: {cacheContext.CacheId} ({Guid.NewGuid()})");
                                writer.WriteLine($"         VARY BY: {String.Join(", ", cacheContext.Contexts)}");
                                writer.WriteLine($"    DEPENDENCIES: {String.Join(", ", cacheContext.Tags)}");
                                writer.WriteLine($"      EXPIRES ON: {cacheContext.ExpiresOn}");
                                writer.WriteLine($"   EXPIRES AFTER: {cacheContext.ExpiresAfter}");
                                writer.WriteLine($" EXPIRES SLIDING: {cacheContext.ExpiresSliding}");
                                writer.WriteLine("-->");
                            }

                            // Always write the content regardless of debug mode.
                            processedContent.WriteTo(writer, HtmlEncoder);

                            // Write the end of a cache debug block.
                            if (_cacheOptions.DebugMode)
                            {
                                writer.WriteLine();
                                writer.WriteLine($"<!-- END CACHE BLOCK: {cacheContext.CacheId} -->");
                            }

                            await writer.FlushAsync();

                            var html = writer.ToString();

                            var formattingContext = new DistributedCacheTagHelperFormattingContext
                            {
                                Html = new HtmlString(html)
                            };

                            await _dynamicCacheService.SetCachedValueAsync(cacheContext, html);

                            content = formattingContext.Html;
                        }
                        else
                        {
                            content = new HtmlString(value);
                        }
                    }
                    catch
                    {
                        content = null;
                        throw;
                    }
                    finally
                    {
                        // Remove the worker task before setting the result.
                        // If the result is null, other threads would potentially
                        // acquire it otherwise.
                        _dynamicCacheTagHelperService.Workers.TryRemove(CacheId, out result);

                        // Notify all other awaiters to render the content
                        tcs.TrySetResult(content);
                    }
                }
                else
                {
                    content = await result;
                }
            }

            return(content);
        }