Make `HtmlEncodedString` a suitable base for MVC's `HtmlString`

- #5
- provide `ToString()` implementation
- add missing `null` checks in `WriteTo()`; remove extraneous one in the constructor
- special-case `HtmlEncodedString` in `IHtmlContentBuilder.AppendFormat()` extension method

nits:
- ignore more files
- add missing `null` checks in `HtmlContentBuilderExtensions` too
This commit is contained in:
Doug Bunting 2015-12-15 15:27:40 -08:00
parent 736f2bcefb
commit 234073cf6e
4 changed files with 81 additions and 13 deletions

12
.gitignore vendored
View File

@ -2,10 +2,17 @@
[Bb]in/ [Bb]in/
TestResults/ TestResults/
.nuget/ .nuget/
*.sln.ide/
_ReSharper.*/ _ReSharper.*/
packages/ packages/
artifacts/ artifacts/
PublishProfiles/ PublishProfiles/
.vs/
bower_components/
node_modules/
**/wwwroot/lib/
debugSettings.json
project.lock.json
*.user *.user
*.suo *.suo
*.cache *.cache
@ -23,5 +30,8 @@ nuget.exe
*.ncrunchsolution *.ncrunchsolution
*.*sdf *.*sdf
*.ipch *.ipch
.settings
*.sln.ide *.sln.ide
project.lock.json node_modules
**/[Cc]ompiler/[Rr]esources/**/*.js
*launchSettings.json

View File

@ -99,6 +99,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder) public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Append(HtmlEncodedString.NewLine); builder.Append(HtmlEncodedString.NewLine);
return builder; return builder;
} }
@ -112,6 +117,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, string unencoded) public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, string unencoded)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Append(unencoded); builder.Append(unencoded);
builder.Append(HtmlEncodedString.NewLine); builder.Append(HtmlEncodedString.NewLine);
return builder; return builder;
@ -125,6 +135,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, IHtmlContent content) public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, IHtmlContent content)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Append(content); builder.Append(content);
builder.Append(HtmlEncodedString.NewLine); builder.Append(HtmlEncodedString.NewLine);
return builder; return builder;
@ -139,6 +154,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder AppendHtmlLine(this IHtmlContentBuilder builder, string encoded) public static IHtmlContentBuilder AppendHtmlLine(this IHtmlContentBuilder builder, string encoded)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.AppendHtml(encoded); builder.AppendHtml(encoded);
builder.Append(HtmlEncodedString.NewLine); builder.Append(HtmlEncodedString.NewLine);
return builder; return builder;
@ -153,6 +173,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, string unencoded) public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, string unencoded)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Clear(); builder.Clear();
builder.Append(unencoded); builder.Append(unencoded);
return builder; return builder;
@ -166,6 +191,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content) public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Clear(); builder.Clear();
builder.Append(content); builder.Append(content);
return builder; return builder;
@ -180,6 +210,11 @@ namespace Microsoft.AspNet.Html
/// <returns>The <see cref="IHtmlContentBuilder"/>.</returns> /// <returns>The <see cref="IHtmlContentBuilder"/>.</returns>
public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, string encoded) public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, string encoded)
{ {
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Clear(); builder.Clear();
builder.AppendHtml(encoded); builder.AppendHtml(encoded);
return builder; return builder;
@ -256,8 +291,14 @@ namespace Microsoft.AspNet.Html
public string Format(string format, object arg, IFormatProvider formatProvider) public string Format(string format, object arg, IFormatProvider formatProvider)
{ {
// This is the case we need to special case. We trust the IHtmlContent instance to do the // These are the cases we need to special case. We trust the HtmlEncodedString or IHtmlContent instance
// right thing with encoding. // to do the right thing with encoding.
var htmlString = arg as HtmlEncodedString;
if (htmlString != null)
{
return htmlString.ToString();
}
var htmlContent = arg as IHtmlContent; var htmlContent = arg as IHtmlContent;
if (htmlContent != null) if (htmlContent != null)
{ {

View File

@ -2,16 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
namespace Microsoft.AspNet.Html namespace Microsoft.AspNet.Html
{ {
/// <summary> /// <summary>
/// An <see cref="IHtmlContent"/> impelementation that wraps an HTML encoded <see cref="string"/>. /// An <see cref="IHtmlContent"/> implementation that wraps an HTML encoded <see cref="string"/>.
/// </summary> /// </summary>
[DebuggerDisplay("{DebuggerToString()}")]
public class HtmlEncodedString : IHtmlContent public class HtmlEncodedString : IHtmlContent
{ {
/// <summary> /// <summary>
@ -27,23 +25,29 @@ namespace Microsoft.AspNet.Html
/// <param name="value">The HTML encoded value.</param> /// <param name="value">The HTML encoded value.</param>
public HtmlEncodedString(string value) public HtmlEncodedString(string value)
{ {
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_value = value; _value = value;
} }
/// <inheritdoc /> /// <inheritdoc />
public void WriteTo(TextWriter writer, HtmlEncoder encoder) public void WriteTo(TextWriter writer, HtmlEncoder encoder)
{ {
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (encoder == null)
{
throw new ArgumentNullException(nameof(encoder));
}
writer.Write(_value); writer.Write(_value);
} }
private string DebuggerToString() /// <inheritdoc />
public override string ToString()
{ {
return _value; return _value ?? string.Empty;
} }
} }
} }

View File

@ -158,6 +158,19 @@ namespace Microsoft.AspNet.Html.Test
HtmlContentToString(builder)); HtmlContentToString(builder));
} }
[Fact]
public void Builder_AppendFormat_HtmlEncodedString()
{
// Arrange
var builder = new TestHtmlContentBuilder();
// Act
builder.AppendFormat("{0}!", new HtmlEncodedString("First"));
// Assert
Assert.Equal("First!", HtmlContentToString(builder));
}
[Fact] [Fact]
public void Builder_AppendFormatContent_With1Argument() public void Builder_AppendFormatContent_With1Argument()
{ {