Merge remote-tracking branch 'origin/release' into dev

This commit is contained in:
Doug Bunting 2015-03-30 11:19:09 -07:00
commit 25376c3377
16 changed files with 147 additions and 66 deletions

View File

@ -61,7 +61,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
SelfClosing = selfClosing;
AllAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
HTMLAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
HTMLAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
TagName = tagName;
Items = items;
UniqueId = uniqueId;
@ -91,7 +91,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <summary>
/// HTML attributes.
/// </summary>
public IDictionary<string, string> HTMLAttributes { get; }
public IDictionary<string, object> HTMLAttributes { get; }
/// <summary>
/// <see cref="ITagHelper"/> bound attributes and HTML attributes.
@ -138,7 +138,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </summary>
/// <param name="name">The HTML attribute name.</param>
/// <param name="value">The HTML attribute value.</param>
public void AddHtmlAttribute([NotNull] string name, string value)
public void AddHtmlAttribute([NotNull] string name, object value)
{
HTMLAttributes.Add(name, value);
AllAttributes.Add(name, value);

View File

@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Internal for testing
internal TagHelperOutput(string tagName)
: this(tagName, new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase))
: this(tagName, new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase))
{
}
@ -31,10 +31,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <param name="attributes">The HTML attributes.</param>
public TagHelperOutput(
string tagName,
[NotNull] IDictionary<string, string> attributes)
[NotNull] IDictionary<string, object> attributes)
{
TagName = tagName;
Attributes = new Dictionary<string, string>(attributes, StringComparer.OrdinalIgnoreCase);
Attributes = new Dictionary<string, object>(attributes, StringComparer.OrdinalIgnoreCase);
_preContent = new DefaultTagHelperContent();
_content = new DefaultTagHelperContent();
_postContent = new DefaultTagHelperContent();
@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <summary>
/// The HTML element's main content.
/// </summary>
/// <remarks>Value occurs in the <see cref="ITagHelper"/>'s final output after <see cref="PreContent"/> and
/// <remarks>Value occurs in the <see cref="ITagHelper"/>'s final output after <see cref="PreContent"/> and
/// before <see cref="PostContent"/></remarks>
public TagHelperContent Content
{
@ -104,7 +104,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <summary>
/// The HTML element's attributes.
/// </summary>
public IDictionary<string, string> Attributes { get; }
/// <remarks>
/// MVC will HTML encode <see cref="string"/> values when generating the start tag. It will not HTML encode
/// a <c>Microsoft.AspNet.Mvc.Rendering.HtmlString</c> instance. MVC converts most other types to a
/// <see cref="string"/>, then HTML encodes the result.
/// </remarks>
public IDictionary<string, object> Attributes { get; }
/// <summary>
/// Changes <see cref="TagHelperOutput"/> to generate nothing.

View File

@ -25,6 +25,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
private readonly CSharpCodeWriter _writer;
private readonly CodeBuilderContext _context;
private readonly IChunkVisitor _bodyVisitor;
private readonly IChunkVisitor _literalBodyVisitor;
private readonly GeneratedTagHelperContext _tagHelperContext;
private readonly bool _designTimeMode;
@ -35,15 +36,18 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
/// <param name="writer">The <see cref="CSharpCodeWriter"/> used to write code.</param>
/// <param name="context">A <see cref="CodeBuilderContext"/> instance that contains information about
/// the current code generation process.</param>
public CSharpTagHelperCodeRenderer([NotNull] IChunkVisitor bodyVisitor,
[NotNull] CSharpCodeWriter writer,
[NotNull] CodeBuilderContext context)
public CSharpTagHelperCodeRenderer(
[NotNull] IChunkVisitor bodyVisitor,
[NotNull] CSharpCodeWriter writer,
[NotNull] CodeBuilderContext context)
{
_bodyVisitor = bodyVisitor;
_writer = writer;
_context = context;
_tagHelperContext = context.Host.GeneratedClassContext.GeneratedTagHelperContext;
_designTimeMode = context.Host.DesignTimeMode;
_literalBodyVisitor = new CSharpLiteralCodeVisitor(this, writer, context);
AttributeValueCodeRenderer = new TagHelperAttributeValueCodeRenderer();
}
@ -55,7 +59,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
/// <param name="chunk">A <see cref="TagHelperChunk"/> to render.</param>
public void RenderTagHelper(TagHelperChunk chunk)
{
// Remove any duplicate TagHelperDescriptors that referrence the same type name. Duplicates can occur when
// Remove any duplicate TagHelperDescriptors that reference the same type name. Duplicates can occur when
// multiple TargetElement attributes are on a TagHelper type and matchs overlap for an HTML element.
// Having more than one descriptor with the same TagHelper type results in generated code that runs
// the same TagHelper X many times (instead of once) over a single HTML element.
@ -214,7 +218,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
// plain text then we need to prepare the value prior to setting it below.
if (!attributeValueRecorded && bufferableAttribute && !isPlainTextValue)
{
BuildBufferedWritingScope(attributeValueChunk);
BuildBufferedWritingScope(attributeValueChunk, htmlEncodeValues: false);
}
// We capture the tag helpers property value accessor so we can retrieve it later (if we need to).
@ -326,7 +330,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
// C# code, then we need to buffer it.
if (!isPlainTextValue)
{
BuildBufferedWritingScope(attributeValue);
BuildBufferedWritingScope(attributeValue, htmlEncodeValues: true);
}
// Execution contexts are a runtime feature, therefore no need to add anything to them.
@ -335,11 +339,13 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
continue;
}
_writer.WriteStartInstanceMethodInvocation(
ExecutionContextVariableName,
_tagHelperContext.ExecutionContextAddHtmlAttributeMethodName);
_writer.WriteStringLiteral(htmlAttribute.Key)
.WriteParameterSeparator();
_writer
.WriteStartInstanceMethodInvocation(
ExecutionContextVariableName,
_tagHelperContext.ExecutionContextAddHtmlAttributeMethodName)
.WriteStringLiteral(htmlAttribute.Key)
.WriteParameterSeparator()
.WriteStartMethodInvocation(_tagHelperContext.MarkAsHtmlEncodedMethodName);
// If it's a plain text value then we need to surround the value with quotes.
if (isPlainTextValue)
@ -351,7 +357,9 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
RenderBufferedAttributeValueAccessor(_writer);
}
_writer.WriteEndMethodInvocation();
_writer
.WriteEndMethodInvocation(endLine: false)
.WriteEndMethodInvocation();
}
}
@ -435,13 +443,8 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
complexValue: false);
}
private void BuildBufferedWritingScope(Chunk htmlAttributeChunk)
{
// Render a buffered writing scope for the html attribute value.
BuildBufferedWritingScope(new[] { htmlAttributeChunk });
}
private void BuildBufferedWritingScope(IList<Chunk> chunks)
// Render a buffered writing scope for the HTML attribute value.
private void BuildBufferedWritingScope(Chunk htmlAttributeChunk, bool htmlEncodeValues)
{
// We're building a writing scope around the provided chunks which captures everything written from the
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
@ -463,7 +466,8 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
_writer.WriteMethodInvocation(_tagHelperContext.StartTagHelperWritingScopeMethodName);
}
_bodyVisitor.Accept(chunks);
var visitor = htmlEncodeValues ? _bodyVisitor : _literalBodyVisitor;
visitor.Accept(htmlAttributeChunk);
// Scopes are a runtime feature.
if (!_designTimeMode)
@ -541,6 +545,37 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
return true;
}
// A CSharpCodeVisitor which does not HTML encode values. Used when rendering bound string attribute values.
private class CSharpLiteralCodeVisitor : CSharpCodeVisitor
{
public CSharpLiteralCodeVisitor(
CSharpTagHelperCodeRenderer tagHelperRenderer,
CSharpCodeWriter writer,
CodeBuilderContext context)
: base(writer, context)
{
// Ensure that no matter how this class is used, we don't create numerous CSharpTagHelperCodeRenderer
// instances.
TagHelperRenderer = tagHelperRenderer;
}
protected override string WriteMethodName
{
get
{
return Context.Host.GeneratedClassContext.WriteLiteralMethodName;
}
}
protected override string WriteToMethodName
{
get
{
return Context.Host.GeneratedClassContext.WriteLiteralToMethodName;
}
}
}
// This class is used to compare tag helper attributes by comparing only the HTML attribute name.
private class TagHelperAttributeDescriptorComparer : IEqualityComparer<TagHelperAttributeDescriptor>
{

View File

@ -22,13 +22,17 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
: base(writer, context)
{
_paddingBuilder = new CSharpPaddingBuilder(context.Host);
TagHelperRenderer = new CSharpTagHelperCodeRenderer(this, writer, context);
}
public CSharpTagHelperCodeRenderer TagHelperRenderer
{
get
{
if (_tagHelperCodeRenderer == null)
{
_tagHelperCodeRenderer = new CSharpTagHelperCodeRenderer(this, Writer, Context);
}
return _tagHelperCodeRenderer;
}
set
@ -42,6 +46,30 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
}
}
/// <summary>
/// Method used to write an <see cref="object"/> to the current output.
/// </summary>
/// <remarks>Default is to HTML encode all but a few types.</remarks>
protected virtual string WriteMethodName
{
get
{
return Context.Host.GeneratedClassContext.WriteMethodName;
}
}
/// <summary>
/// Method used to write an <see cref="object"/> to a specified <see cref="System.IO.TextWriter"/>.
/// </summary>
/// <remarks>Default is to HTML encode all but a few types.</remarks>
protected virtual string WriteToMethodName
{
get
{
return Context.Host.GeneratedClassContext.WriteToMethodName;
}
}
protected override void Visit(TagHelperChunk chunk)
{
TagHelperRenderer.RenderTagHelper(chunk);
@ -394,13 +422,14 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
{
if (!string.IsNullOrEmpty(Context.TargetWriterName))
{
Writer.WriteStartMethodInvocation(Context.Host.GeneratedClassContext.WriteToMethodName)
.Write(Context.TargetWriterName)
.WriteParameterSeparator();
Writer
.WriteStartMethodInvocation(WriteToMethodName)
.Write(Context.TargetWriterName)
.WriteParameterSeparator();
}
else
{
Writer.WriteStartMethodInvocation(Context.Host.GeneratedClassContext.WriteMethodName);
Writer.WriteStartMethodInvocation(WriteMethodName);
}
Accept(chunk.Children);
@ -424,25 +453,30 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
{
if (!string.IsNullOrEmpty(Context.TargetWriterName))
{
var generatedStart = Context.Host.GeneratedClassContext.WriteToMethodName.Length +
Context.TargetWriterName.Length +
3; // 1 for the opening '(' and 2 for ', '
var generatedStart =
WriteToMethodName.Length +
Context.TargetWriterName.Length +
3; // 1 for the opening '(' and 2 for ', '
var padding = _paddingBuilder.BuildExpressionPadding(contentSpan, generatedStart);
Writer.Write(padding)
.WriteStartMethodInvocation(Context.Host.GeneratedClassContext.WriteToMethodName)
.Write(Context.TargetWriterName)
.WriteParameterSeparator();
Writer
.Write(padding)
.WriteStartMethodInvocation(WriteToMethodName)
.Write(Context.TargetWriterName)
.WriteParameterSeparator();
}
else
{
var generatedStart = Context.Host.GeneratedClassContext.WriteMethodName.Length +
1; // for the opening '('
var generatedStart =
WriteMethodName.Length +
1; // for the opening '('
var padding = _paddingBuilder.BuildExpressionPadding(contentSpan, generatedStart);
Writer.Write(padding)
.WriteStartMethodInvocation(Context.Host.GeneratedClassContext.WriteMethodName);
Writer
.Write(padding)
.WriteStartMethodInvocation(WriteMethodName);
}
Accept(chunk.Children);

View File

@ -21,6 +21,7 @@ namespace Microsoft.AspNet.Razor.Generator
ExecutionContextAddTagHelperAttributeMethodName = "AddTagHelperAttribute";
ExecutionContextAddHtmlAttributeMethodName = "AddHtmlAttribute";
ExecutionContextOutputPropertyName = "Output";
MarkAsHtmlEncodedMethodName = "Html.Raw";
StartTagHelperWritingScopeMethodName = "StartTagHelperWritingScope";
EndTagHelperWritingScopeMethodName = "EndTagHelperWritingScope";
RunnerTypeName = "TagHelperRunner";
@ -71,6 +72,12 @@ namespace Microsoft.AspNet.Razor.Generator
/// </summary>
public string ExecutionContextOutputPropertyName { get; set; }
/// <summary>
/// The name of the method used to wrap a <see cref="string"/> value and mark it as HTML-encoded.
/// </summary>
/// <remarks>Used together with <see cref="ExecutionContextAddHtmlAttributeMethodName"/>.</remarks>
public string MarkAsHtmlEncodedMethodName { get; set; }
/// <summary>
/// The name of the method used to start a new writing scope.
/// </summary>

View File

@ -160,7 +160,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
var attribute = Assert.Single(executionContext.HTMLAttributes);
Assert.Equal(new KeyValuePair<string, string>(originalName, "something else"), attribute);
Assert.Equal(new KeyValuePair<string, object>(originalName, "something else"), attribute);
}
[MemberData(nameof(DictionaryCaseTestingData))]
@ -183,7 +183,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var expectedAttributes = new Dictionary<string, string>
var expectedAttributes = new Dictionary<string, object>
{
{ "class", "btn" },
{ "foo", "bar" }

View File

@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p",
attributes: new Dictionary<string, string>
attributes: new Dictionary<string, object>
{
{ "class", "btn" },
{ "something", " spaced " }
@ -129,7 +129,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p",
attributes: new Dictionary<string, string>
attributes: new Dictionary<string, object>
{
{ originalName, "btn" },
});
@ -139,7 +139,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
var attribute = Assert.Single(tagHelperOutput.Attributes);
Assert.Equal(new KeyValuePair<string, string>(originalName, "super button"), attribute);
Assert.Equal(new KeyValuePair<string, object>(originalName, "super button"), attribute);
}
}
}

View File

@ -38,7 +38,7 @@ namespace TestOutput
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("catchAll", "hi");
__tagHelperExecutionContext.AddHtmlAttribute("catchAll", Html.Raw("hi"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
@ -81,7 +81,7 @@ namespace TestOutput
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
__CatchAllTagHelper = CreateTagHelper<CatchAllTagHelper>();
__tagHelperExecutionContext.Add(__CatchAllTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("catchAll", "hi");
__tagHelperExecutionContext.AddHtmlAttribute("catchAll", Html.Raw("hi"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
@ -90,7 +90,7 @@ namespace TestOutput
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", "btn");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("btn"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -77,7 +77,7 @@ namespace TestOutput
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -55,7 +55,7 @@ namespace TestOutput
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -78,7 +78,7 @@ namespace TestOutput
, StartTagHelperWritingScope, EndTagHelperWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -69,8 +69,8 @@ namespace TestOutput
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
__InputTagHelper2.Type = __InputTagHelper.Type;
__tagHelperExecutionContext.AddHtmlAttribute("value", "");
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", "Enter in a new time...");
__tagHelperExecutionContext.AddHtmlAttribute("value", Html.Raw(""));
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", Html.Raw("Enter in a new time..."));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
@ -100,7 +100,7 @@ namespace TestOutput
__tagHelperExecutionContext.Add(__InputTagHelper);
StartTagHelperWritingScope();
#line 16 "ComplexTagHelpers.cshtml"
Write(checkbox);
WriteLiteral(checkbox);
#line default
#line hidden
@ -134,7 +134,7 @@ Write(checkbox);
__tagHelperExecutionContext.Add(__InputTagHelper);
StartTagHelperWritingScope();
#line 17 "ComplexTagHelpers.cshtml"
Write(true ? "checkbox" : "anything");
WriteLiteral(true ? "checkbox" : "anything");
#line default
#line hidden
@ -203,7 +203,7 @@ Write(DateTime.Now);
#line default
#line hidden
__tagHelperStringValueBuffer = EndTagHelperWritingScope();
__tagHelperExecutionContext.AddHtmlAttribute("time", __tagHelperStringValueBuffer.ToString());
__tagHelperExecutionContext.AddHtmlAttribute("time", Html.Raw(__tagHelperStringValueBuffer.ToString()));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -45,7 +45,7 @@ __InputTagHelper2.Checked = ;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
__tagHelperExecutionContext.AddHtmlAttribute("class", "");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw(""));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
@ -70,7 +70,7 @@ __InputTagHelper2.Checked = ;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
__tagHelperExecutionContext.AddHtmlAttribute("class", "");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw(""));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -45,7 +45,7 @@ namespace TestOutput
__tagHelperExecutionContext.Add(__InputTagHelper);
StartTagHelperWritingScope();
#line 6 "EscapedTagHelpers.cshtml"
Write(DateTime.Now);
WriteLiteral(DateTime.Now);
#line default
#line hidden

View File

@ -39,7 +39,7 @@ namespace TestOutput
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
__tagHelperExecutionContext.AddHtmlAttribute("class", Html.Raw("Hello World"));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperAsync(__tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();

View File

@ -64,7 +64,7 @@ namespace TestOutput
StartTagHelperWritingScope();
WriteLiteral("Current Time: ");
#line 9 "TagHelpersInSection.cshtml"
Write(DateTime.Now);
WriteLiteral(DateTime.Now);
#line default
#line hidden
@ -79,7 +79,7 @@ Write(DateTime.Now);
#line default
#line hidden
__tagHelperStringValueBuffer = EndTagHelperWritingScope();
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", Html.Raw(__tagHelperStringValueBuffer.ToString()));
__tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
await WriteTagHelperToAsync(__razor_template_writer, __tagHelperExecutionContext);
__tagHelperExecutionContext = __tagHelperScopeManager.End();