public async Task GetChildContentAsync_CachesValue() { // Arrange var defaultTagHelperContent = new DefaultTagHelperContent(); var content = string.Empty; var expectedContent = string.Empty; var executionContext = new TagHelperExecutionContext( "p", tagMode: TagMode.StartTagAndEndTag, items: new Dictionary<object, object>(), uniqueId: string.Empty, executeChildContentAsync: () => { if (string.IsNullOrEmpty(expectedContent)) { content = "Hello from child content: " + Guid.NewGuid().ToString(); expectedContent = $"HtmlEncode[[{content}]]"; } defaultTagHelperContent.SetContent(content); return Task.FromResult(result: true); }, startTagHelperWritingScope: () => { }, endTagHelperWritingScope: () => defaultTagHelperContent); // Act var content1 = await executionContext.GetChildContentAsync(useCachedResult: true); var content2 = await executionContext.GetChildContentAsync(useCachedResult: true); // Assert Assert.Equal(expectedContent, content1.GetContent(new HtmlTestEncoder())); Assert.Equal(expectedContent, content2.GetContent(new HtmlTestEncoder())); }
public async Task GetChildContentAsync_ReturnsNewObjectEveryTimeItIsCalled(bool useCachedResult) { // Arrange var defaultTagHelperContent = new DefaultTagHelperContent(); var executionContext = new TagHelperExecutionContext( "p", tagMode: TagMode.StartTagAndEndTag, items: new Dictionary<object, object>(), uniqueId: string.Empty, executeChildContentAsync: () => { return Task.FromResult(result: true); }, startTagHelperWritingScope: () => { }, endTagHelperWritingScope: () => defaultTagHelperContent); // Act var content1 = await executionContext.GetChildContentAsync(useCachedResult); content1.Append("Hello"); var content2 = await executionContext.GetChildContentAsync(useCachedResult); content2.Append("World!"); // Assert Assert.NotSame(content1, content2); var content3 = await executionContext.GetChildContentAsync(useCachedResult); Assert.Empty(content3.GetContent(new HtmlTestEncoder())); }
public async Task ProcessAsync_WithItems_GeneratesExpectedOutput_DoesNotChangeSelectList( object model, Type containerType, Func <object> modelAccessor, NameAndId nameAndId, string expectedOptions) { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes) { { "id", nameAndId.Id }, { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent + expectedOptions; var expectedTagName = "select"; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer); var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }) { TagMode = TagMode.SelfClosing, }; output.PreContent.AppendHtml(expectedPreContent); output.Content.AppendHtml(expectedContent); output.PostContent.AppendHtml(originalPostContent); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = { { "valid", "from validation attributes" }, } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); var items = new SelectList(new[] { "", "outer text", "inner text", "other text" }); var savedDisabled = items.Select(item => item.Disabled).ToList(); var savedGroup = items.Select(item => item.Group).ToList(); var savedSelected = items.Select(item => item.Selected).ToList(); var savedText = items.Select(item => item.Text).ToList(); var savedValue = items.Select(item => item.Value).ToList(); var tagHelper = new SelectTagHelper(htmlGenerator) { For = modelExpression, Items = items, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(TagMode.SelfClosing, output.TagMode); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, HtmlContentUtilities.HtmlContentToString(output.PostContent)); Assert.Equal(expectedTagName, output.TagName); Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); Assert.Equal(savedDisabled, items.Select(item => item.Disabled)); Assert.Equal(savedGroup, items.Select(item => item.Group)); Assert.Equal(savedSelected, items.Select(item => item.Selected)); Assert.Equal(savedText, items.Select(item => item.Text)); Assert.Equal(savedValue, items.Select(item => item.Value)); }
public async Task ProcessAsync_WithItems_AndNoModelExpression_GeneratesExpectedOutput() { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes); var selectItems = new SelectList(Enumerable.Range(0, 5)); var expectedOptions = "<option>HtmlEncode[[0]]</option>" + Environment.NewLine + "<option>HtmlEncode[[1]]</option>" + Environment.NewLine + "<option>HtmlEncode[[2]]</option>" + Environment.NewLine + "<option>HtmlEncode[[3]]</option>" + Environment.NewLine + "<option>HtmlEncode[[4]]</option>" + Environment.NewLine; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent + expectedOptions; var expectedTagName = "select"; var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }) { TagMode = TagMode.SelfClosing, }; output.PreContent.AppendHtml(expectedPreContent); output.Content.AppendHtml(expectedContent); output.PostContent.AppendHtml(originalPostContent); var metadataProvider = new TestModelMetadataProvider(); var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext( model: null, htmlGenerator: htmlGenerator, metadataProvider: metadataProvider); var tagHelper = new SelectTagHelper(htmlGenerator) { Items = selectItems, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(TagMode.SelfClosing, output.TagMode); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, HtmlContentUtilities.HtmlContentToString(output.PostContent)); Assert.Equal(expectedTagName, output.TagName); var kvp = Assert.Single(tagHelperContext.Items); Assert.Equal(typeof(SelectTagHelper), kvp.Key); Assert.Null(kvp.Value); }
public async Task ProcessAsync_GeneratesExpectedOutput( object model, Type containerType, Func <object> modelAccessor, NameAndId nameAndId, string ignored) { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes) { { "id", nameAndId.Id }, { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent; var expectedTagName = "not-select"; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer); var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }) { TagMode = TagMode.SelfClosing, }; output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(originalPostContent); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = { { "valid", "from validation attributes" }, } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); var tagHelper = new SelectTagHelper(htmlGenerator) { For = modelExpression, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(TagMode.SelfClosing, output.TagMode); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, output.PostContent.GetContent()); Assert.Equal(expectedTagName, output.TagName); Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); }
public IActionResult Refresh(string data) { try { if (string.IsNullOrWhiteSpace(data)) { return(BadRequest("The data is null or empty.")); } var decryptedModel = _captchaProtectionProvider.Decrypt(data); if (decryptedModel == null) { return(BadRequest("Couldn't decrypt the data.")); } var model = _serializationProvider.Deserialize <DNTCaptchaTagHelperHtmlAttributes>(decryptedModel); if (model == null) { return(BadRequest("Couldn't deserialize the model.")); } invalidateToken(model); var tagHelper = HttpContext.RequestServices.GetRequiredService <DNTCaptchaTagHelper>(); tagHelper.BackColor = model.BackColor; tagHelper.FontName = model.FontName; tagHelper.FontSize = model.FontSize; tagHelper.ForeColor = model.ForeColor; tagHelper.Language = model.Language; tagHelper.Max = model.Max; tagHelper.Min = model.Min; tagHelper.Placeholder = model.Placeholder; tagHelper.TextBoxClass = model.TextBoxClass; tagHelper.TextBoxTemplate = model.TextBoxTemplate; tagHelper.ValidationErrorMessage = model.ValidationErrorMessage; tagHelper.ValidationMessageClass = model.ValidationMessageClass; tagHelper.RefreshButtonClass = model.RefreshButtonClass; tagHelper.DisplayMode = model.DisplayMode; tagHelper.UseRelativeUrls = model.UseRelativeUrls; tagHelper.UseNoise = model.UseNoise; var tagHelperContext = new TagHelperContext( allAttributes: new TagHelperAttributeList(), items: new Dictionary <object, object> { { typeof(IUrlHelper), this.Url } }, uniqueId: Guid.NewGuid().ToString("N")); var tagHelperOutput = new TagHelperOutput( tagName: "div", attributes: new TagHelperAttributeList(), getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent(string.Empty); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); tagHelper.ViewContext = ViewContext ?? new ViewContext( new ActionContext(this.HttpContext, HttpContext.GetRouteData(), ControllerContext.ActionDescriptor), new FakeView(), new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = null }, new TempDataDictionary(this.HttpContext, _tempDataProvider), TextWriter.Null, new HtmlHelperOptions()); tagHelper.Process(tagHelperContext, tagHelperOutput); var attrs = new StringBuilder(); foreach (var attr in tagHelperOutput.Attributes) { attrs.Append(' ').Append(attr.Name).Append("='").Append(attr.Value).Append('\''); } var content = $"<div {attrs}>{tagHelperOutput.Content.GetContent()}</div>"; return(Content(content)); } catch (Exception ex) { _logger.LogError(ex, "Failed to refresh the captcha image."); return(BadRequest(ex.ToString())); } }
private void BuildFallbackBlock(IDictionary <string, object> attributes, DefaultTagHelperContent builder) { EnsureGlobbingUrlBuilder(); EnsureFileVersionProvider(); var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude); if (fallbackSrcs.Any()) { // Build the <script> tag that checks the test method and if it fails, renders the extra script. builder.Append(Environment.NewLine) .Append("<script>(") .Append(FallbackTestExpression) .Append("||document.write(\""); // May have no "src" attribute in the dictionary e.g. if Src and SrcInclude were not bound. if (!attributes.ContainsKey(SrcAttributeName)) { // Need this entry to place each fallback source. attributes.Add(SrcAttributeName, null); } foreach (var src in fallbackSrcs) { // Fallback "src" values come from bound attributes and globbing. Must always be non-null. Debug.Assert(src != null); builder.Append("<script"); foreach (var attribute in attributes) { if (!attribute.Key.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase)) { var encodedKey = JavaScriptEncoder.JavaScriptStringEncode(attribute.Key); var attributeValue = attribute.Value.ToString(); var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true); } else { // Ignore attribute.Value; use src instead. var attributeValue = src; if (FileVersion == true) { attributeValue = _fileVersionProvider.AddFileVersionToPath(attributeValue); } // attribute.Key ("src") does not need to be JavaScript-encoded. var encodedValue = JavaScriptEncoder.JavaScriptStringEncode(attributeValue); AppendAttribute(builder, attribute.Key, encodedValue, escapeQuotes: true); } } builder.Append("><\\/script>"); } builder.Append("\"));</script>"); } }
public async Task WriteTagHelperAsync_WritesContentAppropriately( bool childContentRetrieved, string input, string expected) { // Arrange var defaultTagHelperContent = new DefaultTagHelperContent(); var writer = new StringCollectionTextWriter(Encoding.UTF8); var context = CreateViewContext(writer); var tagHelperExecutionContext = new TagHelperExecutionContext( tagName: "p", tagMode: TagMode.StartTagAndEndTag, items: new Dictionary<object, object>(), uniqueId: string.Empty, executeChildContentAsync: () => { defaultTagHelperContent.AppendHtml(input); return Task.FromResult(result: true); }, startTagHelperWritingScope: () => { }, endTagHelperWritingScope: () => defaultTagHelperContent); tagHelperExecutionContext.Output = new TagHelperOutput( tagName: "p", attributes: new TagHelperAttributeList(), getChildContentAsync: (_) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent())); if (childContentRetrieved) { await tagHelperExecutionContext.GetChildContentAsync(useCachedResult: true); } // Act var page = CreatePage(p => { p.HtmlEncoder = new CommonTestEncoder(); p.WriteTagHelperAsync(tagHelperExecutionContext).Wait(); }, context); await page.ExecuteAsync(); // Assert Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(writer.Content)); }
/// <inheritdoc /> public override void Process(TagHelperContext context, TagHelperOutput output) { string resolvedUrl; // Pass through attribute that is also a well-known HTML attribute. if (Href != null) { output.CopyHtmlAttribute(HrefAttributeName, context); // Resolve any application relative URLs (~/) now so they can be used in comparisons later. if (TryResolveUrl(Href, encodeWebRoot: false, resolvedUrl: out resolvedUrl)) { Href = resolvedUrl; } ProcessUrlAttribute(HrefAttributeName, output); } var modeResult = AttributeMatcher.DetermineMode(context, ModeDetails); modeResult.LogDetails(Logger, this, context.UniqueId, ViewContext.View.Path); if (!modeResult.FullMatches.Any()) { // No attributes matched so we have nothing to do return; } // NOTE: Values in TagHelperOutput.Attributes may already be HTML-encoded. var attributes = new TagHelperAttributeList(output.Attributes); if (AppendVersion == true) { EnsureFileVersionProvider(); var attributeStringValue = output.Attributes[HrefAttributeName]?.Value as string; if (attributeStringValue != null) { output.Attributes[HrefAttributeName].Value = _fileVersionProvider.AddFileVersionToPath(attributeStringValue); } } var builder = new DefaultTagHelperContent(); // Get the highest matched mode var mode = modeResult.FullMatches.Select(match => match.Mode).Max(); if (mode == Mode.GlobbedHref || mode == Mode.Fallback && !string.IsNullOrEmpty(HrefInclude)) { BuildGlobbedLinkTags(attributes, builder); if (string.IsNullOrEmpty(Href)) { // Only HrefInclude is specified. Don't render the original tag. output.TagName = null; output.Content.SetContent(string.Empty); } } if (mode == Mode.Fallback) { if (TryResolveUrl(FallbackHref, encodeWebRoot: false, resolvedUrl: out resolvedUrl)) { FallbackHref = resolvedUrl; } BuildFallbackBlock(builder); } output.PostElement.SetContent(builder); }