Replaced WebUtility.HtmlEncode with IHtmlEncoder.HtmlEncode

This commit is contained in:
Ajay Bhargav Baaskaran 2015-02-26 18:06:06 -08:00
parent 4bd02badda
commit 7ecce1b666
20 changed files with 220 additions and 31 deletions

View File

@ -4,9 +4,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Text;
using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
@ -19,6 +19,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private bool _contentSet;
private bool _isTagNameNullOrWhitespace;
private string _tagName;
private readonly IHtmlEncoder _htmlEncoder;
// Internal for testing
internal TagHelperOutput(string tagName)
@ -32,13 +33,19 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </summary>
/// <param name="tagName">The HTML element's tag name.</param>
/// <param name="attributes">The HTML attributes.</param>
public TagHelperOutput(string tagName, [NotNull] IDictionary<string, string> attributes)
/// <param name="htmlEncoder">The <see cref="IHtmlEncoder"/> used
/// to encode HTML attribute values.</param>
public TagHelperOutput(
string tagName,
[NotNull] IDictionary<string, string> attributes,
[NotNull] IHtmlEncoder htmlEncoder)
{
TagName = tagName;
Attributes = new Dictionary<string, string>(attributes, StringComparer.OrdinalIgnoreCase);
PreContent = string.Empty;
_content = string.Empty;
PostContent = string.Empty;
_htmlEncoder = htmlEncoder;
}
/// <summary>
@ -131,7 +138,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
foreach (var attribute in Attributes)
{
var value = WebUtility.HtmlEncode(attribute.Value);
var value = _htmlEncoder.HtmlEncode(attribute.Value);
sb.Append(' ')
.Append(attribute.Key)
.Append("=\"")

View File

@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
@ -12,6 +13,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </summary>
public class TagHelperRunner
{
private readonly IHtmlEncoder _htmlEncoder;
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperRunner"/>.
/// </summary>
/// <param name="htmlEncoder">The <see cref="IHtmlEncoder"/> used to encode HTML.</param>
public TagHelperRunner([NotNull] IHtmlEncoder htmlEncoder)
{
_htmlEncoder = htmlEncoder;
}
/// <summary>
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
/// </summary>
@ -26,7 +38,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
executionContext.Items,
executionContext.UniqueId,
executionContext.GetChildContentAsync);
var tagHelperOutput = new TagHelperOutput(executionContext.TagName, executionContext.HTMLAttributes)
var tagHelperOutput = new TagHelperOutput(
executionContext.TagName,
executionContext.HTMLAttributes,
_htmlEncoder)
{
SelfClosing = executionContext.SelfClosing,
};

View File

@ -4,7 +4,8 @@
"dependencies": {
"Microsoft.AspNet.Razor": "4.0.0-*",
"Microsoft.Framework.CopyOnWriteDictionary.Internal": { "type": "build", "version": "1.0.0-*" },
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" }
"Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" },
"Microsoft.Framework.WebEncoders": "1.0.0-*"
},
"frameworks": {
"net45": { },

View File

@ -66,6 +66,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
{
using (writer.BuildMethodDeclaration("public override async", "Task", Host.GeneratedClassContext.ExecuteMethodName))
{
new CSharpTagHelperRunnerInitializationVisitor(writer, Context).Accept(Tree.Chunks);
csharpCodeVisitor.Accept(Tree.Chunks);
}
}

View File

@ -46,13 +46,19 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
CSharpTagHelperCodeRenderer.ExecutionContextVariableName,
value: null);
WritePrivateField(_tagHelperContext.RunnerTypeName,
CSharpTagHelperCodeRenderer.RunnerVariableName,
"new " + _tagHelperContext.RunnerTypeName + "()");
Writer
.Write("private ")
.WriteVariableDeclaration(
_tagHelperContext.RunnerTypeName,
CSharpTagHelperCodeRenderer.RunnerVariableName,
value: null);
WritePrivateField(_tagHelperContext.ScopeManagerTypeName,
CSharpTagHelperCodeRenderer.ScopeManagerVariableName,
"new " + _tagHelperContext.ScopeManagerTypeName + "()");
Writer.Write("private ")
.Write(_tagHelperContext.ScopeManagerTypeName)
.Write(" ")
.WriteStartAssignment(CSharpTagHelperCodeRenderer.ScopeManagerVariableName)
.WriteStartNewObject(_tagHelperContext.ScopeManagerTypeName)
.WriteEndMethodInvocation();
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
{
/// <summary>
/// The <see cref="CodeVisitor{T}"/> that generates the code to initialize the TagHelperRunner.
/// </summary>
public class CSharpTagHelperRunnerInitializationVisitor : CodeVisitor<CSharpCodeWriter>
{
private readonly GeneratedTagHelperContext _tagHelperContext;
private bool _foundTagHelpers;
/// <summary>
/// Creates a new instance of <see cref="CSharpTagHelperRunnerInitializationVisitor"/>.
/// </summary>
/// <param name="writer">The <see cref="CSharpCodeWriter"/> used to generate code.</param>
/// <param name="context">The <see cref="CodeBuilderContext"/>.</param>
public CSharpTagHelperRunnerInitializationVisitor([NotNull] CSharpCodeWriter writer,
[NotNull] CodeBuilderContext context)
: base(writer, context)
{
_tagHelperContext = Context.Host.GeneratedClassContext.GeneratedTagHelperContext;
}
/// <summary>
/// Writes the TagHelperRunner initialization code to the Writer.
/// </summary>
/// <param name="chunk">The <see cref="TagHelperChunk"/>.</param>
protected override void Visit(TagHelperChunk chunk)
{
if (!_foundTagHelpers && !Context.Host.DesignTimeMode)
{
_foundTagHelpers = true;
Writer
.WriteStartAssignment(CSharpTagHelperCodeRenderer.RunnerVariableName)
.Write(CSharpTagHelperCodeRenderer.RunnerVariableName)
.Write(" ?? ")
.WriteStartNewObject(_tagHelperContext.RunnerTypeName)
.Write(_tagHelperContext.HtmlEncoderPropertyName)
.WriteEndMethodInvocation();
}
}
}
}

View File

@ -35,6 +35,7 @@ namespace Microsoft.AspNet.Razor.Generator
RunnerTypeName = "TagHelperRunner";
ScopeManagerTypeName = "TagHelperScopeManager";
ExecutionContextTypeName = "TagHelperExecutionContext";
HtmlEncoderPropertyName = "HtmlEncoder";
}
/// <summary>
@ -150,5 +151,10 @@ namespace Microsoft.AspNet.Razor.Generator
/// Contains information about in-scope tag helpers, HTML attributes, and the tag helpers' output.
/// </remarks>
public string ExecutionContextTypeName { get; set; }
/// <summary>
/// The name of the property used to encode HTML.
/// </summary>
public string HtmlEncoderPropertyName { get; set; }
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers.Test
{
public class NullHtmlEncoder : IHtmlEncoder
{
public string HtmlEncode(string value)
{
return value;
}
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
{
output.Write(value.Substring(startIndex, charCount));
}
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
{
output.Write(value, startIndex, charCount);
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers.Test
{
public class PseudoHtmlEncoder : IHtmlEncoder
{
public string HtmlEncode(string value)
{
return "HtmlEncode[[" + value + "]]";
}
public void HtmlEncode(string value, int startIndex, int charCount, TextWriter output)
{
output.Write("HtmlEncode[[");
output.Write(value.Substring(startIndex, charCount));
output.Write("]]");
}
public void HtmlEncode(char[] value, int startIndex, int charCount, TextWriter output)
{
output.Write("HtmlEncode[[");
output.Write(value, startIndex, charCount);
output.Write("]]");
}
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Runtime.TagHelpers.Test;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
@ -79,7 +80,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
{ "class", "btn" },
{ "something", " spaced " }
});
},
htmlEncoder: new NullHtmlEncoder());
// Act
var output = tagHelperOutput.GenerateStartTag();
@ -110,7 +112,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
{ "class", "btn" },
{ "something", " spaced " }
});
},
htmlEncoder: new NullHtmlEncoder());
tagHelperOutput.SelfClosing = true;
@ -136,6 +139,26 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Equal("<p />", output);
}
[Fact]
public void GenerateStartTag_UsesProvidedHtmlEncoder()
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p",
attributes: new Dictionary<string, string>
{
{ "hello", "world" },
},
htmlEncoder: new PseudoHtmlEncoder());
tagHelperOutput.SelfClosing = true;
// Act
var output = tagHelperOutput.GenerateStartTag();
// Assert
Assert.Equal("<p hello=\"HtmlEncode[[world]]\" />", output);
}
[Fact]
public void GenerateStartTag_ReturnsNothingIfWhitespaceTagName()
{
@ -145,7 +168,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
{ "class", "btn" },
{ "something", " spaced " }
})
},
htmlEncoder: new NullHtmlEncoder())
{
SelfClosing = true
};
@ -402,7 +426,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
{ "class", "btn" },
{ "something", " spaced " }
})
},
htmlEncoder: new NullHtmlEncoder())
{
PreContent = "Pre Content",
Content = "Content",
@ -431,7 +456,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
attributes: new Dictionary<string, string>
{
{ originalName, "btn" },
});
},
htmlEncoder: new NullHtmlEncoder());
// Act
tagHelperOutput.Attributes[updateName] = "super button";

View File

@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNet.Razor.Runtime.TagHelpers.Test;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
@ -61,7 +62,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
int[] expectedTagHelperOrders)
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var processOrder = new List<int>();
@ -87,7 +88,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public async Task RunAsync_SetTagHelperOutputSelfClosing(bool selfClosing)
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing);
var tagHelper = new TagHelperContextTouchingTagHelper();
@ -105,7 +106,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public async Task RunAsync_ProcessesAllTagHelpers()
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var executableTagHelper1 = new ExecutableTagHelper();
var executableTagHelper2 = new ExecutableTagHelper();
@ -124,7 +125,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public async Task RunAsync_AllowsModificationOfTagHelperOutput()
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var executableTagHelper = new ExecutableTagHelper();
@ -144,7 +145,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public async Task RunAsync_AllowsDataRetrievalFromTagHelperContext()
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var tagHelper = new TagHelperContextTouchingTagHelper();
@ -161,7 +162,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public async Task RunAsync_ConfiguresTagHelperContextWithExecutionContextsItems()
{
// Arrange
var runner = new TagHelperRunner();
var runner = new TagHelperRunner(new NullHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var tagHelper = new ContextInspectingTagHelper();
executionContext.Add(tagHelper);
@ -174,6 +175,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Same(tagHelper.ContextProcessedWith.Items, executionContext.Items);
}
[Fact]
public async Task RunAsync_CreatesTagHelperOutput_WithProvidedEncoder()
{
// Arrange
var runner = new TagHelperRunner(new PseudoHtmlEncoder());
var executionContext = new TagHelperExecutionContext("p", selfClosing: true);
executionContext.AddHtmlAttribute("Hello", "World");
// Act
var tagHelperOutput = await runner.RunAsync(executionContext);
var output = tagHelperOutput.GenerateStartTag();
// Assert
Assert.Equal("<p Hello=\"HtmlEncode[[World]]\" />", output);
}
private class ExecutableTagHelper : TagHelper
{
public bool Processed { get; set; }

View File

@ -11,7 +11,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
@ -24,6 +24,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(33, 49, true);
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
@ -25,6 +25,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(57, 52, true);
WriteLiteral("\r\n<THSdiv class=\"randomNonTagHelperAttribute\">\r\n ");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
@ -25,6 +25,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(33, 49, true);
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
@ -25,6 +25,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(33, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
@ -25,6 +25,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(27, 13, true);
WriteLiteral("\r\n<div>\r\n ");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
@ -24,6 +24,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(27, 72, true);
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n <p class=\"Hello World\" ");
Instrumentation.EndContext();

View File

@ -12,7 +12,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private PTagHelper __PTagHelper = null;
#line hidden
@ -23,6 +23,7 @@ namespace TestOutput
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(33, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();

View File

@ -120,7 +120,7 @@ Write(DateTime.Now);
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private MyTagHelper __MyTagHelper = null;
private NestedTagHelper __NestedTagHelper = null;
@ -132,6 +132,7 @@ Write(DateTime.Now);
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(HtmlEncoder);
Instrumentation.BeginContext(33, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();

View File

@ -11,7 +11,7 @@ namespace TestOutput
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperRunner __tagHelperRunner = null;
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private MyTagHelper __MyTagHelper = null;
private NestedTagHelper __NestedTagHelper = null;