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); }