Replaced WebUtility.HtmlEnode with IHtmlEncoder.HtmlEncode

This commit is contained in:
Ajay Bhargav Baaskaran 2015-02-17 12:09:44 -08:00
parent e4b1242328
commit 81c3b75980
54 changed files with 658 additions and 348 deletions

View File

@ -7,6 +7,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
@ -22,13 +23,14 @@ namespace Microsoft.AspNet.Mvc
public AntiForgery([NotNull] IClaimUidExtractor claimUidExtractor, public AntiForgery([NotNull] IClaimUidExtractor claimUidExtractor,
[NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] IDataProtectionProvider dataProtectionProvider,
[NotNull] IAntiForgeryAdditionalDataProvider additionalDataProvider, [NotNull] IAntiForgeryAdditionalDataProvider additionalDataProvider,
[NotNull] IOptions<MvcOptions> mvcOptions) [NotNull] IOptions<MvcOptions> mvcOptions,
[NotNull] IHtmlEncoder htmlEncoder)
{ {
var config = mvcOptions.Options.AntiForgeryOptions; var config = mvcOptions.Options.AntiForgeryOptions;
var serializer = new AntiForgeryTokenSerializer(dataProtectionProvider.CreateProtector(_purpose)); var serializer = new AntiForgeryTokenSerializer(dataProtectionProvider.CreateProtector(_purpose));
var tokenStore = new AntiForgeryTokenStore(config, serializer); var tokenStore = new AntiForgeryTokenStore(config, serializer);
var tokenProvider = new TokenProvider(config, claimUidExtractor, additionalDataProvider); var tokenProvider = new TokenProvider(config, claimUidExtractor, additionalDataProvider);
_worker = new AntiForgeryWorker(serializer, config, tokenStore, tokenProvider, tokenProvider); _worker = new AntiForgeryWorker(serializer, config, tokenStore, tokenProvider, tokenProvider, htmlEncoder);
} }
/// <summary> /// <summary>

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
@ -19,18 +20,21 @@ namespace Microsoft.AspNet.Mvc
private readonly ITokenStore _tokenStore; private readonly ITokenStore _tokenStore;
private readonly ITokenValidator _validator; private readonly ITokenValidator _validator;
private readonly ITokenGenerator _generator; private readonly ITokenGenerator _generator;
private readonly IHtmlEncoder _htmlEncoder;
internal AntiForgeryWorker([NotNull] IAntiForgeryTokenSerializer serializer, internal AntiForgeryWorker([NotNull] IAntiForgeryTokenSerializer serializer,
[NotNull] AntiForgeryOptions config, [NotNull] AntiForgeryOptions config,
[NotNull] ITokenStore tokenStore, [NotNull] ITokenStore tokenStore,
[NotNull] ITokenGenerator generator, [NotNull] ITokenGenerator generator,
[NotNull] ITokenValidator validator) [NotNull] ITokenValidator validator,
[NotNull] IHtmlEncoder htmlEncoder)
{ {
_serializer = serializer; _serializer = serializer;
_config = config; _config = config;
_tokenStore = tokenStore; _tokenStore = tokenStore;
_generator = generator; _generator = generator;
_validator = validator; _validator = validator;
_htmlEncoder = htmlEncoder;
} }
private void CheckSSLConfig(HttpContext httpContext) private void CheckSSLConfig(HttpContext httpContext)
@ -107,11 +111,16 @@ namespace Microsoft.AspNet.Mvc
SaveCookieTokenAndHeader(httpContext, newCookieToken); SaveCookieTokenAndHeader(httpContext, newCookieToken);
// <input type="hidden" name="__AntiForgeryToken" value="..." /> // <input type="hidden" name="__AntiForgeryToken" value="..." />
var retVal = new TagBuilder("input"); var inputTag = new TagBuilder("input", _htmlEncoder)
retVal.Attributes["type"] = "hidden"; {
retVal.Attributes["name"] = _config.FormFieldName; Attributes =
retVal.Attributes["value"] = _serializer.Serialize(formToken); {
return retVal; { "type", "hidden" },
{ "name", _config.FormFieldName },
{ "value", _serializer.Serialize(formToken) }
}
};
return inputTag;
} }
// [ ENTRY POINT ] // [ ENTRY POINT ]

View File

@ -5,7 +5,6 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Text; using System.Text;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
@ -25,12 +24,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
return htmlHelper.ViewData.ModelMetadata.IsNullableValueType ? return htmlHelper.ViewData.ModelMetadata.IsNullableValueType ?
BooleanTemplateDropDownList(htmlHelper, value) : BooleanTemplateDropDownList(htmlHelper, value) :
BooleanTemplateCheckbox(value ?? false); BooleanTemplateCheckbox(value ?? false, htmlHelper);
} }
private static string BooleanTemplateCheckbox(bool value) private static string BooleanTemplateCheckbox(bool value, IHtmlHelper htmlHelper)
{ {
var inputTag = new TagBuilder("input"); var inputTag = new TagBuilder("input", htmlHelper.HtmlEncoder);
inputTag.AddCssClass("check-box"); inputTag.AddCssClass("check-box");
inputTag.Attributes["disabled"] = "disabled"; inputTag.Attributes["disabled"] = "disabled";
inputTag.Attributes["type"] = "checkbox"; inputTag.Attributes["type"] = "checkbox";
@ -44,7 +43,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
private static string BooleanTemplateDropDownList(IHtmlHelper htmlHelper, bool? value) private static string BooleanTemplateDropDownList(IHtmlHelper htmlHelper, bool? value)
{ {
var selectTag = new TagBuilder("select"); var selectTag = new TagBuilder("select", htmlHelper.HtmlEncoder);
selectTag.AddCssClass("list-box"); selectTag.AddCssClass("list-box");
selectTag.AddCssClass("tri-state"); selectTag.AddCssClass("tri-state");
selectTag.Attributes["disabled"] = "disabled"; selectTag.Attributes["disabled"] = "disabled";
@ -55,7 +54,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
foreach (var item in TriStateValues(value)) foreach (var item in TriStateValues(value))
{ {
var encodedText = htmlHelper.Encode(item.Text); var encodedText = htmlHelper.Encode(item.Text);
var option = DefaultHtmlGenerator.GenerateOption(item, encodedText); var option = DefaultHtmlGenerator.GenerateOption(item, encodedText, htmlHelper.HtmlEncoder);
builder.Append(option); builder.Append(option);
} }
@ -181,7 +180,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string.Empty : string.Empty :
htmlHelper.ViewData.TemplateInfo.FormattedModelValue.ToString(); htmlHelper.ViewData.TemplateInfo.FormattedModelValue.ToString();
return HyperlinkTemplate(uriString, linkedText); return HyperlinkTemplate(uriString, linkedText, htmlHelper);
} }
public static string HiddenInputTemplate(IHtmlHelper htmlHelper) public static string HiddenInputTemplate(IHtmlHelper htmlHelper)
@ -233,7 +232,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
var divTag = new TagBuilder("div"); var divTag = new TagBuilder("div", htmlHelper.HtmlEncoder);
if (!propertyMetadata.HideSurroundingHtml) if (!propertyMetadata.HideSurroundingHtml)
{ {
@ -293,13 +292,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
string.Empty : string.Empty :
htmlHelper.ViewData.TemplateInfo.FormattedModelValue.ToString(); htmlHelper.ViewData.TemplateInfo.FormattedModelValue.ToString();
return HyperlinkTemplate(uriString, linkedText); return HyperlinkTemplate(uriString, linkedText, htmlHelper);
} }
// Neither uriString nor linkedText need be encoded prior to calling this method. // Neither uriString nor linkedText need be encoded prior to calling this method.
private static string HyperlinkTemplate(string uriString, string linkedText) private static string HyperlinkTemplate(string uriString, string linkedText, IHtmlHelper htmlHelper)
{ {
var hyperlinkTag = new TagBuilder("a"); var hyperlinkTag = new TagBuilder("a", htmlHelper.HtmlEncoder);
hyperlinkTag.MergeAttribute("href", uriString); hyperlinkTag.MergeAttribute("href", uriString);
hyperlinkTag.SetInnerText(linkedText); hyperlinkTag.SetInnerText(linkedText);

View File

@ -257,7 +257,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
var divTag = new TagBuilder("div"); var divTag = new TagBuilder("div", htmlHelper.HtmlEncoder);
if (!propertyMetadata.HideSurroundingHtml) if (!propertyMetadata.HideSurroundingHtml)
{ {

View File

@ -7,13 +7,13 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering.Expressions; using Microsoft.AspNet.Mvc.Rendering.Expressions;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
@ -25,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
private readonly IScopedInstance<ActionBindingContext> _bindingContextAccessor; private readonly IScopedInstance<ActionBindingContext> _bindingContextAccessor;
private readonly IModelMetadataProvider _metadataProvider; private readonly IModelMetadataProvider _metadataProvider;
private readonly IUrlHelper _urlHelper; private readonly IUrlHelper _urlHelper;
private readonly IHtmlEncoder _htmlEncoder;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DefaultHtmlGenerator"/> class. /// Initializes a new instance of the <see cref="DefaultHtmlGenerator"/> class.
@ -33,12 +34,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
[NotNull] AntiForgery antiForgery, [NotNull] AntiForgery antiForgery,
[NotNull] IScopedInstance<ActionBindingContext> bindingContextAccessor, [NotNull] IScopedInstance<ActionBindingContext> bindingContextAccessor,
[NotNull] IModelMetadataProvider metadataProvider, [NotNull] IModelMetadataProvider metadataProvider,
[NotNull] IUrlHelper urlHelper) [NotNull] IUrlHelper urlHelper,
[NotNull] IHtmlEncoder htmlEncoder)
{ {
_antiForgery = antiForgery; _antiForgery = antiForgery;
_bindingContextAccessor = bindingContextAccessor; _bindingContextAccessor = bindingContextAccessor;
_metadataProvider = metadataProvider; _metadataProvider = metadataProvider;
_urlHelper = urlHelper; _urlHelper = urlHelper;
_htmlEncoder = htmlEncoder;
// Underscores are fine characters in id's. // Underscores are fine characters in id's.
IdAttributeDotReplacement = "_"; IdAttributeDotReplacement = "_";
@ -50,13 +53,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <inheritdoc /> /// <inheritdoc />
public string Encode(string value) public string Encode(string value)
{ {
return !string.IsNullOrEmpty(value) ? WebUtility.HtmlEncode(value) : string.Empty; return !string.IsNullOrEmpty(value) ? _htmlEncoder.HtmlEncode(value) : string.Empty;
} }
/// <inheritdoc /> /// <inheritdoc />
public string Encode(object value) public string Encode(object value)
{ {
return (value != null) ? WebUtility.HtmlEncode(value.ToString()) : string.Empty; return (value != null) ? _htmlEncoder.HtmlEncode(value.ToString()) : string.Empty;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -138,7 +141,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
ModelExplorer modelExplorer, ModelExplorer modelExplorer,
string expression) string expression)
{ {
var tagBuilder = new TagBuilder("input"); var tagBuilder = new TagBuilder("input", _htmlEncoder);
tagBuilder.MergeAttribute("type", GetInputTypeString(InputType.Hidden)); tagBuilder.MergeAttribute("type", GetInputTypeString(InputType.Hidden));
tagBuilder.MergeAttribute("value", "false"); tagBuilder.MergeAttribute("value", "false");
@ -252,7 +255,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return null; return null;
} }
var tagBuilder = new TagBuilder("label"); var tagBuilder = new TagBuilder("label", _htmlEncoder);
var idString = var idString =
TagBuilder.CreateSanitizedId(GetFullHtmlFieldName(viewContext, expression), IdAttributeDotReplacement); TagBuilder.CreateSanitizedId(GetFullHtmlFieldName(viewContext, expression), IdAttributeDotReplacement);
tagBuilder.Attributes.Add("for", idString); tagBuilder.Attributes.Add("for", idString);
@ -454,7 +457,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
// Convert each ListItem to an <option> tag and wrap them with <optgroup> if requested. // Convert each ListItem to an <option> tag and wrap them with <optgroup> if requested.
var listItemBuilder = GenerateGroupsAndOptions(optionLabel, selectList); var listItemBuilder = GenerateGroupsAndOptions(optionLabel, selectList);
var tagBuilder = new TagBuilder("select") var tagBuilder = new TagBuilder("select", _htmlEncoder)
{ {
InnerHtml = listItemBuilder.ToString() InnerHtml = listItemBuilder.ToString()
}; };
@ -521,7 +524,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
value = modelExplorer.Model.ToString(); value = modelExplorer.Model.ToString();
} }
var tagBuilder = new TagBuilder("textarea"); var tagBuilder = new TagBuilder("textarea", _htmlEncoder);
tagBuilder.GenerateId(fullName, IdAttributeDotReplacement); tagBuilder.GenerateId(fullName, IdAttributeDotReplacement);
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes), true); tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes), true);
if (rows > 0) if (rows > 0)
@ -545,7 +548,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
// The first newline is always trimmed when a TextArea is rendered, so we add an extra one // The first newline is always trimmed when a TextArea is rendered, so we add an extra one
// in case the value being rendered is something like "\r\nHello". // in case the value being rendered is something like "\r\nHello".
tagBuilder.InnerHtml = Environment.NewLine + WebUtility.HtmlEncode(value); tagBuilder.InnerHtml = Environment.NewLine + _htmlEncoder.HtmlEncode(value);
return tagBuilder; return tagBuilder;
} }
@ -615,7 +618,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{ {
tag = viewContext.ValidationMessageElement; tag = viewContext.ValidationMessageElement;
} }
var tagBuilder = new TagBuilder(tag); var tagBuilder = new TagBuilder(tag, _htmlEncoder);
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes)); tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
// Only the style of the span is changed according to the errors if message is null or empty. // Only the style of the span is changed according to the errors if message is null or empty.
@ -668,7 +671,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
{ {
headerTag = viewContext.ValidationSummaryMessageElement; headerTag = viewContext.ValidationSummaryMessageElement;
} }
var messageTag = new TagBuilder(headerTag); var messageTag = new TagBuilder(headerTag, _htmlEncoder);
messageTag.SetInnerText(message); messageTag.SetInnerText(message);
wrappedMessage = messageTag.ToString(TagRenderMode.Normal) + Environment.NewLine; wrappedMessage = messageTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
} }
@ -690,7 +693,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
if (!string.IsNullOrEmpty(errorText)) if (!string.IsNullOrEmpty(errorText))
{ {
var listItem = new TagBuilder("li"); var listItem = new TagBuilder("li", _htmlEncoder);
listItem.SetInnerText(errorText); listItem.SetInnerText(errorText);
htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal)); htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
} }
@ -702,12 +705,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlSummary.AppendLine(HiddenListItem); htmlSummary.AppendLine(HiddenListItem);
} }
var unorderedList = new TagBuilder("ul") var unorderedList = new TagBuilder("ul", _htmlEncoder)
{ {
InnerHtml = htmlSummary.ToString() InnerHtml = htmlSummary.ToString()
}; };
var tagBuilder = new TagBuilder("div"); var tagBuilder = new TagBuilder("div", _htmlEncoder);
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes)); tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
if (viewContext.ViewData.ModelState.IsValid) if (viewContext.ViewData.ModelState.IsValid)
@ -758,9 +761,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <remarks> /// <remarks>
/// Not used directly in HtmlHelper. Exposed for use in DefaultDisplayTemplates. /// Not used directly in HtmlHelper. Exposed for use in DefaultDisplayTemplates.
/// </remarks> /// </remarks>
internal static TagBuilder GenerateOption(SelectListItem item, string encodedText) internal static TagBuilder GenerateOption(SelectListItem item, string encodedText, IHtmlEncoder htmlEncoder)
{ {
var tagBuilder = new TagBuilder("option") var tagBuilder = new TagBuilder("option", htmlEncoder)
{ {
InnerHtml = encodedText, InnerHtml = encodedText,
}; };
@ -819,7 +822,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string method, string method,
object htmlAttributes) object htmlAttributes)
{ {
var tagBuilder = new TagBuilder("form"); var tagBuilder = new TagBuilder("form", _htmlEncoder);
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes)); tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
// action is implicitly generated from other parameters, so htmlAttributes take precedence. // action is implicitly generated from other parameters, so htmlAttributes take precedence.
@ -860,7 +863,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression)); throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(expression));
} }
var tagBuilder = new TagBuilder("input"); var tagBuilder = new TagBuilder("input", _htmlEncoder);
tagBuilder.MergeAttributes(htmlAttributes); tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", GetInputTypeString(inputType)); tagBuilder.MergeAttribute("type", GetInputTypeString(inputType));
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true); tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
@ -945,9 +948,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
[NotNull] string url, [NotNull] string url,
object htmlAttributes) object htmlAttributes)
{ {
var tagBuilder = new TagBuilder("a") var tagBuilder = new TagBuilder("a", _htmlEncoder)
{ {
InnerHtml = WebUtility.HtmlEncode(linkText), InnerHtml = _htmlEncoder.HtmlEncode(linkText),
}; };
tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes)); tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
@ -1127,7 +1130,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
TagBuilder groupBuilder = null; TagBuilder groupBuilder = null;
if (optGroup != null) if (optGroup != null)
{ {
groupBuilder = new TagBuilder("optgroup"); groupBuilder = new TagBuilder("optgroup", _htmlEncoder);
if (optGroup.Name != null) if (optGroup.Name != null)
{ {
groupBuilder.MergeAttribute("label", optGroup.Name); groupBuilder.MergeAttribute("label", optGroup.Name);
@ -1158,7 +1161,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
private string GenerateOption(SelectListItem item) private string GenerateOption(SelectListItem item)
{ {
var encodedText = Encode(item.Text); var encodedText = Encode(item.Text);
var tagBuilder = GenerateOption(item, encodedText); var tagBuilder = GenerateOption(item, encodedText, _htmlEncoder);
return tagBuilder.ToString(TagRenderMode.Normal); return tagBuilder.ToString(TagRenderMode.Normal);
} }

View File

@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering.Expressions; using Microsoft.AspNet.Mvc.Rendering.Expressions;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
@ -37,11 +38,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
public HtmlHelper( public HtmlHelper(
[NotNull] IHtmlGenerator htmlGenerator, [NotNull] IHtmlGenerator htmlGenerator,
[NotNull] ICompositeViewEngine viewEngine, [NotNull] ICompositeViewEngine viewEngine,
[NotNull] IModelMetadataProvider metadataProvider) [NotNull] IModelMetadataProvider metadataProvider,
[NotNull] IHtmlEncoder htmlEncoder,
[NotNull] IUrlEncoder urlEncoder,
[NotNull] IJavaScriptStringEncoder javaScriptStringEncoder)
{ {
_viewEngine = viewEngine; _viewEngine = viewEngine;
_htmlGenerator = htmlGenerator; _htmlGenerator = htmlGenerator;
MetadataProvider = metadataProvider; MetadataProvider = metadataProvider;
HtmlEncoder = htmlEncoder;
UrlEncoder = urlEncoder;
JavaScriptStringEncoder = javaScriptStringEncoder;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -107,7 +114,16 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
/// <inheritdoc /> /// <inheritdoc />
public IModelMetadataProvider MetadataProvider { get; private set; } public IHtmlEncoder HtmlEncoder { get; }
/// <inheritdoc />
public IUrlEncoder UrlEncoder { get; }
/// <inheritdoc />
public IJavaScriptStringEncoder JavaScriptStringEncoder { get; }
/// <inheritdoc />
public IModelMetadataProvider MetadataProvider { get; }
/// <summary> /// <summary>
/// Creates a dictionary from an object, by adding each public instance property as a key with its associated /// Creates a dictionary from an object, by adding each public instance property as a key with its associated

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering.Expressions; using Microsoft.AspNet.Mvc.Rendering.Expressions;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
@ -19,8 +20,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
public HtmlHelper( public HtmlHelper(
[NotNull] IHtmlGenerator htmlGenerator, [NotNull] IHtmlGenerator htmlGenerator,
[NotNull] ICompositeViewEngine viewEngine, [NotNull] ICompositeViewEngine viewEngine,
[NotNull] IModelMetadataProvider metadataProvider) [NotNull] IModelMetadataProvider metadataProvider,
: base(htmlGenerator, viewEngine, metadataProvider) [NotNull] IHtmlEncoder htmlEncoder,
[NotNull] IUrlEncoder urlEncoder,
[NotNull] IJavaScriptStringEncoder javaScriptStringEncoder)
: base(htmlGenerator, viewEngine, metadataProvider, htmlEncoder, urlEncoder, javaScriptStringEncoder)
{ {
} }

View File

@ -4,18 +4,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Net; using System.IO;
using System.Text; using System.Text;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
public class TagBuilder public class TagBuilder
{ {
private string _innerHtml; private string _innerHtml;
private readonly IHtmlEncoder _htmlEncoder;
public TagBuilder(string tagName) public TagBuilder(string tagName)
: this(tagName, HtmlEncoder.Default)
{
}
public TagBuilder(string tagName, [NotNull] IHtmlEncoder htmlEncoder)
{ {
if (string.IsNullOrEmpty(tagName)) if (string.IsNullOrEmpty(tagName))
{ {
@ -24,6 +31,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
TagName = tagName; TagName = tagName;
Attributes = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase); Attributes = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
_htmlEncoder = htmlEncoder;
} }
public IDictionary<string, string> Attributes { get; private set; } public IDictionary<string, string> Attributes { get; private set; }
@ -106,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
} }
private void AppendAttributes(StringBuilder sb) private void AppendAttributes(TextWriter textWriter)
{ {
foreach (var attribute in Attributes) foreach (var attribute in Attributes)
{ {
@ -117,12 +125,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
continue; continue;
} }
var value = WebUtility.HtmlEncode(attribute.Value); textWriter.Write(' ');
sb.Append(' ') textWriter.Write(key);
.Append(key) textWriter.Write("=\"");
.Append("=\"") _htmlEncoder.HtmlEncode(attribute.Value, textWriter);
.Append(value) textWriter.Write('"');
.Append('"');
} }
} }
@ -164,7 +171,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void SetInnerText(string innerText) public void SetInnerText(string innerText)
{ {
InnerHtml = WebUtility.HtmlEncode(innerText); InnerHtml = _htmlEncoder.HtmlEncode(innerText);
} }
public HtmlString ToHtmlString(TagRenderMode renderMode) public HtmlString ToHtmlString(TagRenderMode renderMode)
@ -179,39 +186,41 @@ namespace Microsoft.AspNet.Mvc.Rendering
public string ToString(TagRenderMode renderMode) public string ToString(TagRenderMode renderMode)
{ {
var sb = new StringBuilder(); using (var stringWriter = new StringWriter())
switch (renderMode)
{ {
case TagRenderMode.StartTag: switch (renderMode)
sb.Append('<') {
.Append(TagName); case TagRenderMode.StartTag:
AppendAttributes(sb); stringWriter.Write('<');
sb.Append('>'); stringWriter.Write(TagName);
break; AppendAttributes(stringWriter);
case TagRenderMode.EndTag: stringWriter.Write('>');
sb.Append("</") break;
.Append(TagName) case TagRenderMode.EndTag:
.Append('>'); stringWriter.Write("</");
break; stringWriter.Write(TagName);
case TagRenderMode.SelfClosing: stringWriter.Write('>');
sb.Append('<') break;
.Append(TagName); case TagRenderMode.SelfClosing:
AppendAttributes(sb); stringWriter.Write('<');
sb.Append(" />"); stringWriter.Write(TagName);
break; AppendAttributes(stringWriter);
default: stringWriter.Write(" />");
sb.Append('<') break;
.Append(TagName); default:
AppendAttributes(sb); stringWriter.Write('<');
sb.Append('>') stringWriter.Write(TagName);
.Append(InnerHtml) AppendAttributes(stringWriter);
.Append("</") stringWriter.Write('>');
.Append(TagName) stringWriter.Write(InnerHtml);
.Append('>'); stringWriter.Write("</");
break; stringWriter.Write(TagName);
} stringWriter.Write('>');
break;
}
return sb.ToString(); return stringWriter.ToString();
}
} }
private static class Html401IdUtil private static class Html401IdUtil

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
@ -45,6 +46,21 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </summary> /// </summary>
ViewDataDictionary ViewData { get; } ViewDataDictionary ViewData { get; }
/// <summary>
/// Gets the <see cref="IHtmlEncoder"/> to be used for encoding HTML.
/// </summary>
IHtmlEncoder HtmlEncoder { get; }
/// <summary>
/// Gets the <see cref="IUrlEncoder"/> to be used for encoding a URL.
/// </summary>
IUrlEncoder UrlEncoder { get; }
/// <summary>
/// Gets the <see cref="IJavaScriptStringEncoder"/> to be used for encoding JavaScript.
/// </summary>
IJavaScriptStringEncoder JavaScriptStringEncoder { get; }
/// <summary> /// <summary>
/// Returns an anchor (&lt;a&gt;) element that contains a URL path to the specified action. /// Returns an anchor (&lt;a&gt;) element that contains a URL path to the specified action.
/// </summary> /// </summary>

View File

@ -100,6 +100,7 @@ namespace Microsoft.AspNet.Mvc.Razor
CreateTagHelperMethodName = "CreateTagHelper", CreateTagHelperMethodName = "CreateTagHelper",
StartWritingScopeMethodName = "StartWritingScope", StartWritingScopeMethodName = "StartWritingScope",
EndWritingScopeMethodName = "EndWritingScope", EndWritingScopeMethodName = "EndWritingScope",
HtmlEncoderPropertyName = "HtmlEncoder",
}) })
{ {
ResolveUrlMethodName = "Href", ResolveUrlMethodName = "Href",

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
@ -14,6 +13,7 @@ using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
@ -61,6 +61,12 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <inheritdoc /> /// <inheritdoc />
public bool IsPartial { get; set; } public bool IsPartial { get; set; }
/// <summary>
/// Gets the <see cref="IHtmlEncoder"/> to be used for encoding HTML.
/// </summary>
[Activate]
public IHtmlEncoder HtmlEncoder { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public IPageExecutionContext PageExecutionContext { get; set; } public IPageExecutionContext PageExecutionContext { get; set; }
@ -264,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))
{ {
writer.Write(WebUtility.HtmlEncode(value)); HtmlEncoder.HtmlEncode(value, writer);
} }
} }

View File

@ -2,10 +2,8 @@
// 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.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc.TagHelpers.Internal; using Microsoft.AspNet.Mvc.TagHelpers.Internal;
@ -152,6 +150,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Activate] [Activate]
protected internal IMemoryCache Cache { get; set; } protected internal IMemoryCache Cache { get; set; }
[Activate]
protected internal IHtmlEncoder HtmlEncoder { get; set; }
// Internal for ease of use when testing. // Internal for ease of use when testing.
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; } protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
@ -207,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
foreach (var url in urls) foreach (var url in urls)
{ {
attributes["href"] = WebUtility.HtmlEncode(url); attributes["href"] = HtmlEncoder.HtmlEncode(url);
BuildLinkTag(attributes, builder); BuildLinkTag(attributes, builder);
} }
} }
@ -225,7 +226,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
builder.AppendFormat( builder.AppendFormat(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
"<meta name=\"x-stylesheet-fallback-test\" class=\"{0}\" />", "<meta name=\"x-stylesheet-fallback-test\" class=\"{0}\" />",
WebUtility.HtmlEncode(FallbackTestClass)); HtmlEncoder.HtmlEncode(FallbackTestClass));
// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra // Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
// <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false, // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,

View File

@ -3,10 +3,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
@ -135,6 +133,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Internal for ease of use when testing. // Internal for ease of use when testing.
protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; } protected internal GlobbingUrlBuilder GlobbingUrlBuilder { get; set; }
[Activate]
protected internal IHtmlEncoder HtmlEncoder { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{ {
@ -191,7 +192,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
foreach (var url in urls) foreach (var url in urls)
{ {
attributes["src"] = WebUtility.HtmlEncode(url); attributes["src"] = HtmlEncoder.HtmlEncode(url);
var content = string.Equals(url, staticSrc, StringComparison.OrdinalIgnoreCase) var content = string.Equals(url, staticSrc, StringComparison.OrdinalIgnoreCase)
? originalContent ? originalContent
: string.Empty; : string.Empty;
@ -283,7 +284,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
content.Append(" ") content.Append(" ")
.Append(srcKey) .Append(srcKey)
.Append("=\\\"") .Append("=\\\"")
.Append(WebUtility.HtmlEncode(srcValue)) .Append(HtmlEncoder.HtmlEncode(srcValue))
.Append("\\\""); .Append("\\\"");
} }
} }

View File

@ -134,6 +134,7 @@ namespace Microsoft.Framework.DependencyInjection
services.AddDataProtection(configuration); services.AddDataProtection(configuration);
services.AddRouting(configuration); services.AddRouting(configuration);
services.AddAuthorization(configuration); services.AddAuthorization(configuration);
services.AddWebEncoders();
services.Configure<RouteOptions>(routeOptions => services.Configure<RouteOptions>(routeOptions =>
routeOptions.ConstraintMap routeOptions.ConstraintMap
.Add("exists", .Add("exists",

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Core.Collections; using Microsoft.AspNet.Http.Core.Collections;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -34,7 +35,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
serializer: null, serializer: null,
tokenStore: null, tokenStore: null,
generator: null, generator: null,
validator: null); validator: null,
htmlEncoder: new HtmlEncoder());
// Act & assert // Act & assert
var ex = var ex =
@ -65,7 +67,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
serializer: null, serializer: null,
tokenStore: null, tokenStore: null,
generator: null, generator: null,
validator: null); validator: null,
htmlEncoder: new HtmlEncoder());
// Act & assert // Act & assert
var ex = Assert.Throws<InvalidOperationException>( var ex = Assert.Throws<InvalidOperationException>(
@ -94,7 +97,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
serializer: null, serializer: null,
tokenStore: null, tokenStore: null,
generator: null, generator: null,
validator: null); validator: null,
htmlEncoder: new HtmlEncoder());
// Act & assert // Act & assert
var ex = Assert.Throws<InvalidOperationException>(() => worker.GetFormInputElement(mockHttpContext.Object)); var ex = Assert.Throws<InvalidOperationException>(() => worker.GetFormInputElement(mockHttpContext.Object));
@ -122,7 +126,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
serializer: null, serializer: null,
tokenStore: null, tokenStore: null,
generator: null, generator: null,
validator: null); validator: null,
htmlEncoder: new HtmlEncoder());
// Act & assert // Act & assert
var ex = Assert.Throws<InvalidOperationException>(() => worker.GetTokens(mockHttpContext.Object, "cookie-token")); var ex = Assert.Throws<InvalidOperationException>(() => worker.GetTokens(mockHttpContext.Object, "cookie-token"));
@ -409,7 +414,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
serializer: context.TokenSerializer != null ? context.TokenSerializer.Object : null, serializer: context.TokenSerializer != null ? context.TokenSerializer.Object : null,
tokenStore: context.TokenStore != null ? context.TokenStore.Object : null, tokenStore: context.TokenStore != null ? context.TokenStore.Object : null,
generator: context.TokenProvider != null ? context.TokenProvider.Object : null, generator: context.TokenProvider != null ? context.TokenProvider.Object : null,
validator: context.TokenProvider != null ? context.TokenProvider.Object : null); validator: context.TokenProvider != null ? context.TokenProvider.Object : null,
htmlEncoder: new HtmlEncoder());
} }
private Mock<HttpContext> GetHttpContext(bool setupResponse = true) private Mock<HttpContext> GetHttpContext(bool setupResponse = true)

View File

@ -5,6 +5,7 @@ using Microsoft.AspNet.DataProtection;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback; using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -39,7 +40,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
return new AntiForgery(claimExtractor.Object, return new AntiForgery(claimExtractor.Object,
dataProtectionProvider.Object, dataProtectionProvider.Object,
additionalDataProvider.Object, additionalDataProvider.Object,
optionsAccessor.Object); optionsAccessor.Object,
new HtmlEncoder());
} }
} }
} }

View File

@ -29,17 +29,17 @@ namespace Microsoft.AspNet.Mvc.Core
{ "<blink>text</blink>", false, "<blink>text</blink>" }, { "<blink>text</blink>", false, "<blink>text</blink>" },
{ "<blink>text</blink>", true, "&lt;blink&gt;text&lt;/blink&gt;" }, { "<blink>text</blink>", true, "&lt;blink&gt;text&lt;/blink&gt;" },
{ "&'\"", false, "&'\"" }, { "&'\"", false, "&'\"" },
{ "&'\"", true, "&amp;&#39;&quot;" }, { "&'\"", true, "&amp;&#x27;&quot;" },
{ " ¡ÿĀ", false, " ¡ÿĀ" }, // high ASCII { " ¡ÿĀ", false, " ¡ÿĀ" }, // high ASCII
{ " ¡ÿĀ", true, "&#160;&#161;&#255;Ā" }, { " ¡ÿĀ", true, "&#xA0;&#xA1;&#xFF;&#x100;" },
{ "Chinese西雅图Chars", false, "Chinese西雅图Chars" }, { "Chinese西雅图Chars", false, "Chinese西雅图Chars" },
{ "Chinese西雅图Chars", true, "Chinese西雅图Chars" }, { "Chinese西雅图Chars", true, "Chinese&#x897F;&#x96C5;&#x56FE;Chars" },
{ "Unicode؃Format؃Char", false, "Unicode؃Format؃Char" }, // class Cf { "Unicode؃Format؃Char", false, "Unicode؃Format؃Char" }, // class Cf
{ "Unicode؃Format؃Char", true, "Unicode؃Format؃Char" }, { "Unicode؃Format؃Char", true, "Unicode&#x603;Format&#x603;Char" },
{ "UnicodeῼTitlecaseῼChar", false, "UnicodeῼTitlecaseῼChar" }, // class Lt { "UnicodeῼTitlecaseῼChar", false, "UnicodeῼTitlecaseῼChar" }, // class Lt
{ "UnicodeῼTitlecaseῼChar", true, "UnicodeῼTitlecaseῼChar" }, { "UnicodeῼTitlecaseῼChar", true, "Unicode&#x1FFC;Titlecase&#x1FFC;Char" },
{ "UnicodeCombiningChar", false, "UnicodeCombiningChar" }, // class Mc { "UnicodeCombiningChar", false, "UnicodeCombiningChar" }, // class Mc
{ "UnicodeCombiningChar", true, "UnicodeCombiningChar" }, { "UnicodeCombiningChar", true, "Unicode&#x903;Combining&#x903;Char" },
}; };
} }
} }

View File

@ -12,6 +12,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -527,8 +528,8 @@ Environment.NewLine;
// DateTime-local is not special-cased unless using Html5DateRenderingMode.Rfc3339. // DateTime-local is not special-cased unless using Html5DateRenderingMode.Rfc3339.
[Theory] [Theory]
[InlineData("date", "{0:d}", "02/01/2000")] [InlineData("date", "{0:d}", "02/01/2000")]
[InlineData("datetime", null, "02/01/2000 03:04:05 +00:00")] [InlineData("datetime", null, "02/01/2000 03:04:05 &#x2B;00:00")]
[InlineData("datetime-local", null, "02/01/2000 03:04:05 +00:00")] [InlineData("datetime-local", null, "02/01/2000 03:04:05 &#x2B;00:00")]
[InlineData("time", "{0:t}", "03:04")] [InlineData("time", "{0:t}", "03:04")]
[ReplaceCulture] [ReplaceCulture]
public void Editor_FindsCorrectDateOrTimeTemplate(string dataTypeName, string editFormatString, string expected) public void Editor_FindsCorrectDateOrTimeTemplate(string dataTypeName, string editFormatString, string expected)
@ -564,7 +565,7 @@ Environment.NewLine;
[Theory] [Theory]
[InlineData("date", "{0:d}", "2000-01-02")] [InlineData("date", "{0:d}", "2000-01-02")]
[InlineData("datetime", null, "2000-01-02T03:04:05.060+00:00")] [InlineData("datetime", null, "2000-01-02T03:04:05.060&#x2B;00:00")]
[InlineData("datetime-local", null, "2000-01-02T03:04:05.060")] [InlineData("datetime-local", null, "2000-01-02T03:04:05.060")]
[InlineData("time", "{0:t}", "03:04:05.060")] [InlineData("time", "{0:t}", "03:04:05.060")]
[ReplaceCulture] [ReplaceCulture]
@ -615,7 +616,7 @@ Environment.NewLine;
{ {
// Arrange // Arrange
var expectedInput = "<input class=\"text-box single-line\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"" + var expectedInput = "<input class=\"text-box single-line\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"" +
dataTypeName + "\" value=\"Formatted as 2000-01-02T03:04:05.0600000+00:00\" />"; dataTypeName + "\" value=\"Formatted as 2000-01-02T03:04:05.0600000&#x2B;00:00\" />";
var offset = TimeSpan.FromHours(0); var offset = TimeSpan.FromHours(0);
var model = new DateTimeOffset( var model = new DateTimeOffset(
year: 2000, year: 2000,
@ -808,6 +809,21 @@ Environment.NewLine;
get { return _innerHelper.ViewData; } get { return _innerHelper.ViewData; }
} }
public IHtmlEncoder HtmlEncoder
{
get { return _innerHelper.HtmlEncoder; }
}
public IUrlEncoder UrlEncoder
{
get { return _innerHelper.UrlEncoder; }
}
public IJavaScriptStringEncoder JavaScriptStringEncoder
{
get { return _innerHelper.JavaScriptStringEncoder; }
}
public void Contextualize([NotNull] ViewContext viewContext) public void Contextualize([NotNull] ViewContext viewContext)
{ {
(_innerHelper as ICanHasViewContext)?.Contextualize(viewContext); (_innerHelper as ICanHasViewContext)?.Contextualize(viewContext);

View File

@ -12,6 +12,7 @@ using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
@ -191,11 +192,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
GetAntiForgeryInstance(), GetAntiForgeryInstance(),
bindingContextAccessor, bindingContextAccessor,
provider, provider,
urlHelper); urlHelper,
new HtmlEncoder());
} }
// TemplateRenderer will Contextualize this transient service. // TemplateRenderer will Contextualize this transient service.
var innerHelper = (IHtmlHelper)new HtmlHelper(htmlGenerator, viewEngine, provider); var innerHelper = (IHtmlHelper)new HtmlHelper(
htmlGenerator,
viewEngine,
provider,
new HtmlEncoder(),
new UrlEncoder(),
new JavaScriptStringEncoder());
if (innerHelperWrapper != null) if (innerHelperWrapper != null)
{ {
innerHelper = innerHelperWrapper(innerHelper); innerHelper = innerHelperWrapper(innerHelper);
@ -204,7 +212,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
.Setup(s => s.GetService(typeof(IHtmlHelper))) .Setup(s => s.GetService(typeof(IHtmlHelper)))
.Returns(() => innerHelper); .Returns(() => innerHelper);
var htmlHelper = new HtmlHelper<TModel>(htmlGenerator, viewEngine, provider); var htmlHelper = new HtmlHelper<TModel>(
htmlGenerator,
viewEngine,
provider,
new HtmlEncoder(),
new UrlEncoder(),
new JavaScriptStringEncoder());
var viewContext = new ViewContext(actionContext, Mock.Of<IView>(), viewData, new StringWriter()); var viewContext = new ViewContext(actionContext, Mock.Of<IView>(), viewData, new StringWriter());
htmlHelper.Contextualize(viewContext); htmlHelper.Contextualize(viewContext);
@ -244,21 +258,24 @@ namespace Microsoft.AspNet.Mvc.Rendering
var additionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>(); var additionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>();
var optionsAccessor = new Mock<IOptions<MvcOptions>>(); var optionsAccessor = new Mock<IOptions<MvcOptions>>();
optionsAccessor.SetupGet(o => o.Options).Returns(new MvcOptions()); optionsAccessor.SetupGet(o => o.Options).Returns(new MvcOptions());
return new AntiForgery(claimExtractor.Object, return new AntiForgery(
dataProtectionProvider.Object, claimExtractor.Object,
additionalDataProvider.Object, dataProtectionProvider.Object,
optionsAccessor.Object); additionalDataProvider.Object,
optionsAccessor.Object,
new HtmlEncoder());
} }
private static string FormatOutput(ModelExplorer modelExplorer) private static string FormatOutput(ModelExplorer modelExplorer)
{ {
var metadata = modelExplorer.Metadata; var metadata = modelExplorer.Metadata;
return string.Format(CultureInfo.InvariantCulture, return string.Format(
"Model = {0}, ModelType = {1}, PropertyName = {2}, SimpleDisplayText = {3}", CultureInfo.InvariantCulture,
modelExplorer.Model ?? "(null)", "Model = {0}, ModelType = {1}, PropertyName = {2}, SimpleDisplayText = {3}",
metadata.ModelType == null ? "(null)" : metadata.ModelType.FullName, modelExplorer.Model ?? "(null)",
metadata.PropertyName ?? "(null)", metadata.ModelType == null ? "(null)" : metadata.ModelType.FullName,
modelExplorer.GetSimpleDisplayText() ?? "(null)"); metadata.PropertyName ?? "(null)",
modelExplorer.GetSimpleDisplayText() ?? "(null)");
} }
private static IUrlHelper CreateUrlHelper() private static IUrlHelper CreateUrlHelper()

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -275,7 +276,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void BeginFormWithNoParameters_CallsHtmlGeneratorWithExpectedValues() public void BeginFormWithNoParameters_CallsHtmlGeneratorWithExpectedValues()
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -309,7 +310,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void BeginFormWithMethodParameter_CallsHtmlGeneratorWithExpectedValues(FormMethod method) public void BeginFormWithMethodParameter_CallsHtmlGeneratorWithExpectedValues(FormMethod method)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -345,7 +346,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
object htmlAttributes) object htmlAttributes)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -379,7 +380,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void BeginFormWithRouteValuesParameter_CallsHtmlGeneratorWithExpectedValues(object routeValues) public void BeginFormWithRouteValuesParameter_CallsHtmlGeneratorWithExpectedValues(object routeValues)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -415,7 +416,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string controllerName) string controllerName)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -452,7 +453,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
object routeValues) object routeValues)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -489,7 +490,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
FormMethod method) FormMethod method)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -527,7 +528,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
FormMethod method) FormMethod method)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -565,7 +566,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
object htmlAttributes) object htmlAttributes)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -599,7 +600,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void BeginRouteFormWithRouteValuesParameter_CallsHtmlGeneratorWithExpectedValues(object routeValues) public void BeginRouteFormWithRouteValuesParameter_CallsHtmlGeneratorWithExpectedValues(object routeValues)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -632,7 +633,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
public void BeginRouteFormWithRouteNameParameter_CallsHtmlGeneratorWithExpectedValues(string routeName) public void BeginRouteFormWithRouteNameParameter_CallsHtmlGeneratorWithExpectedValues(string routeName)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -667,7 +668,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
object routeValues) object routeValues)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -702,7 +703,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
FormMethod method) FormMethod method)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -738,7 +739,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
FormMethod method) FormMethod method)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator
@ -774,7 +775,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
object htmlAttributes) object htmlAttributes)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder(tagName: "form"); var tagBuilder = new TagBuilder(tagName: "form", htmlEncoder: new HtmlEncoder());
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(htmlGenerator.Object);
htmlGenerator htmlGenerator

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.Core.Rendering namespace Microsoft.AspNet.Mvc.Core.Rendering
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
public void MergeAttribute_IgnoresCase(bool replaceExisting, string expectedKey, string expectedValue) public void MergeAttribute_IgnoresCase(bool replaceExisting, string expectedKey, string expectedValue)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add("Hello", "World"); tagBuilder.Attributes.Add("Hello", "World");
// Act // Act
@ -43,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
public void AddCssClass_IgnoresCase() public void AddCssClass_IgnoresCase()
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add("ClaSs", "btn"); tagBuilder.Attributes.Add("ClaSs", "btn");
// Act // Act
@ -58,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
public void GenerateId_IgnoresCase() public void GenerateId_IgnoresCase()
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add("ID", "something"); tagBuilder.Attributes.Add("ID", "something");
// Act // Act
@ -69,11 +70,12 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
Assert.Equal(new KeyValuePair<string, string>("ID", "something"), attribute); Assert.Equal(new KeyValuePair<string, string>("ID", "something"), attribute);
} }
[Theory]
[MemberData(nameof(RenderingTestingData))] [MemberData(nameof(RenderingTestingData))]
public void ToString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput) public void ToString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
// An empty value id attribute should not be rendered via ToString. // An empty value id attribute should not be rendered via ToString.
tagBuilder.Attributes.Add("ID", string.Empty); tagBuilder.Attributes.Add("ID", string.Empty);
@ -85,11 +87,12 @@ namespace Microsoft.AspNet.Mvc.Core.Rendering
Assert.Equal(expectedOutput, value); Assert.Equal(expectedOutput, value);
} }
[Theory]
[MemberData(nameof(RenderingTestingData))] [MemberData(nameof(RenderingTestingData))]
public void ToHtmlString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput) public void ToHtmlString_IgnoresIdAttributeCase(TagRenderMode renderingMode, string expectedOutput)
{ {
// Arrange // Arrange
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
// An empty value id attribute should not be rendered via ToHtmlString. // An empty value id attribute should not be rendered via ToHtmlString.
tagBuilder.Attributes.Add("ID", string.Empty); tagBuilder.Attributes.Add("ID", string.Empty);

View File

@ -1,9 +1,9 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Net;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Mvc
// Arrange // Arrange
var viewComponent = new TestViewComponent(); var viewComponent = new TestViewComponent();
var expectedContent = "TestContent&"; var expectedContent = "TestContent&";
var expectedEncodedContent = new HtmlString(WebUtility.HtmlEncode(expectedContent)); var expectedEncodedContent = new HtmlString(new HtmlEncoder().HtmlEncode(expectedContent));
// Act // Act
var actualResult = viewComponent.Content(expectedContent); var actualResult = viewComponent.Content(expectedContent);

View File

@ -4,6 +4,6 @@
<title>Action Link with non unicode host</title> <title>Action Link with non unicode host</title>
</head> </head>
<body> <body>
<a href="http://ping&#252;ino/Home/ActionLinkView">Ping&#252;ino</a> <a href="http://ping&#xFC;ino/Home/ActionLinkView">Ping&#xFC;ino</a>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
<div class="left"> <div class="left">
<form action="/vehicles/42/edit" method="post"><div class="validation-summary-errors" data-valmsg-summary="true"><ul><li>The field Vin must be a string with a maximum length of 8.</li> <form action="/vehicles/42/edit" method="post"><div class="validation-summary-errors" data-valmsg-summary="true"><ul><li>The field Vin must be a string with a maximum length of 8.</li>
<li>The field Year must be between 1980 and 2034.</li> <li>The field Year must be between 1980 and 2034.</li>
<li>The field InspectedDates must be a string or array type with a maximum length of &#39;10&#39;.</li> <li>The field InspectedDates must be a string or array type with a maximum length of &#x27;10&#x27;.</li>
</ul></div><div class="editor-label"><label for="Model">Model</label></div> </ul></div><div class="editor-label"><label for="Model">Model</label></div>
<div class="editor-field"><input class="text-box single-line" id="Model" name="Model" type="text" value="the Fastener" /> <span class="field-validation-valid" data-valmsg-for="Model" data-valmsg-replace="true"></span></div> <div class="editor-field"><input class="text-box single-line" id="Model" name="Model" type="text" value="the Fastener" /> <span class="field-validation-valid" data-valmsg-for="Model" data-valmsg-replace="true"></span></div>
<div class="editor-label"><label for="Make">Make</label></div> <div class="editor-label"><label for="Make">Make</label></div>

View File

@ -14,7 +14,7 @@
<label for="InspectedDates">InspectedDates</label> <label for="InspectedDates">InspectedDates</label>
</div> </div>
<div class="editor-field"> <div class="editor-field">
<input class="text-box single-line" id="InspectedDates_0_" name="InspectedDates[0]" type="datetime" value="01/04/2001 00:00:00 -08:00" /><input class="text-box single-line" id="InspectedDates_1_" name="InspectedDates[1]" type="datetime" value="01/01/0001 00:00:00 +00:00" /> <input class="text-box single-line" id="InspectedDates_0_" name="InspectedDates[0]" type="datetime" value="01/04/2001 00:00:00 -08:00" /><input class="text-box single-line" id="InspectedDates_1_" name="InspectedDates[1]" type="datetime" value="01/01/0001 00:00:00 &#x2B;00:00" />
</div> </div>
<input type="submit" value="Update" /> <input type="submit" value="Update" />
</form></div> </form></div>

View File

@ -5,7 +5,7 @@
<body> <body>
<form action="/MvcTagHelper_Home/CreateWarehouse" method="post"> <div> <form action="/MvcTagHelper_Home/CreateWarehouse" method="post"> <div>
<label class="warehouse" for="City">City</label> <label class="warehouse" for="City">City</label>
<input size="50" type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#39;2&#39;." data-val-minlength-min="2" id="City" name="City" value="" /> <input size="50" type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#x27;2&#x27;." data-val-minlength-min="2" id="City" name="City" value="" />
<span class="field-validation-valid" data-valmsg-for="City" data-valmsg-replace="true"></span> <span class="field-validation-valid" data-valmsg-for="City" data-valmsg-replace="true"></span>
</div> </div>
<div> <div>

View File

@ -6,7 +6,7 @@
<form action="/MvcTagHelper_Home/EditWarehouse" method="post"> <form action="/MvcTagHelper_Home/EditWarehouse" method="post">
<div> <div>
City_1 City_1
<input type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#39;2&#39;." data-val-minlength-min="2" id="City" name="City" value="City_1" /> <input type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#x27;2&#x27;." data-val-minlength-min="2" id="City" name="City" value="City_1" />
</div> </div>
<div> <div>
<label>Address</label> <label>Address</label>

View File

@ -19,7 +19,7 @@
<hr /> <hr />
<div class="text-danger validation-summary-errors" data-valmsg-summary="true"> <div class="text-danger validation-summary-errors" data-valmsg-summary="true">
<ul><li>The field Age must be between 10 and 100.</li> <ul><li>The field Age must be between 10 and 100.</li>
<li>The value &#39;z&#39; is not valid for Salary.</li> <li>The value &#x27;z&#x27; is not valid for Salary.</li>
<li>The JoinDate field is required.</li> <li>The JoinDate field is required.</li>
</ul></div> </ul></div>
<div class="form-group"> <div class="form-group">
@ -55,7 +55,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="JoinDate">JoinDate</label> <label class="control-label col-md-2" for="JoinDate">JoinDate</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control input-validation-error" type="date" data-val="true" data-val-required="The JoinDate field is required." id="JoinDate" name="JoinDate" value="01/01/0001 00:00:00 +00:00" /> <input class="form-control input-validation-error" type="date" data-val="true" data-val-required="The JoinDate field is required." id="JoinDate" name="JoinDate" value="01/01/0001 00:00:00 &#x2B;00:00" />
<span class="field-validation-error" data-valmsg-for="JoinDate" data-valmsg-replace="true">The JoinDate field is required.</span> <span class="field-validation-error" data-valmsg-for="JoinDate" data-valmsg-replace="true">The JoinDate field is required.</span>
</div> </div>
</div> </div>
@ -63,7 +63,7 @@
<label class="control-label col-md-2" for="Salary">Salary</label> <label class="control-label col-md-2" for="Salary">Salary</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control input-validation-error" type="number" id="Salary" name="Salary" value="z" /> <input class="form-control input-validation-error" type="number" id="Salary" name="Salary" value="z" />
<span class="field-validation-error" data-valmsg-for="Salary" data-valmsg-replace="true">The value &#39;z&#39; is not valid for Salary.</span> <span class="field-validation-error" data-valmsg-for="Salary" data-valmsg-replace="true">The value &#x27;z&#x27; is not valid for Salary.</span>
</div> </div>
</div> </div>

View File

@ -11,24 +11,9 @@
</head> </head>
<body> <body>
<h1 style="font-family: cursive;">ASP.NET vNext - About</h1> <h1 style="font-family: cursive;">ASP.NET vNext - About</h1>
<p>| <a href="/" style="background-color: gray; <p>| <a href="/" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Home</a>
color: white; | <a href="/home/about" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My About</a>
border-radius: 3px; | <a href="/home/help" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Help</a> |</p>
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Home</a>
| <a href="/home/about" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My About</a>
| <a href="/home/help" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Help</a> |</p>
<div> <div>

View File

@ -11,24 +11,9 @@
</head> </head>
<body> <body>
<h1 style="font-family: cursive;">ASP.NET vNext - Help</h1> <h1 style="font-family: cursive;">ASP.NET vNext - Help</h1>
<p>| <a href="/" style="background-color: gray; <p>| <a href="/" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Home</a>
color: white; | <a href="/home/about" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My About</a>
border-radius: 3px; | <a href="/home/help" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Help</a> |</p>
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Home</a>
| <a href="/home/about" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My About</a>
| <a href="/home/help" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Help</a> |</p>
<div> <div>

View File

@ -18,24 +18,9 @@
</head> </head>
<body> <body>
<h1 style="font-family: cursive;">ASP.NET vNext - Home Page</h1> <h1 style="font-family: cursive;">ASP.NET vNext - Home Page</h1>
<p>| <a href="/" style="background-color: gray; <p>| <a href="/" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Home</a>
color: white; | <a href="/home/about" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My About</a>
border-radius: 3px; | <a href="/home/help" style="background-color: gray;color: white;border-radius: 3px;border: 1px solid black;padding: 3px;font-family: cursive;">My Help</a> |</p>
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Home</a>
| <a href="/home/about" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My About</a>
| <a href="/home/help" style="background-color: gray;
color: white;
border-radius: 3px;
border: 1px solid black;
padding: 3px;
font-family: cursive;">My Help</a> |</p>
<div> <div>
@ -43,8 +28,7 @@
<div> <div>
<p>This website has <strong style="font-size: 1.25em; <p>This website has <strong style="font-size: 1.25em;text-decoration: underline;">not</strong> been approved yet. Visit <strong><a target="_blank" href="http://www.contoso.com">www.contoso.com</a></strong> for <strong>more</strong> information.</p>
text-decoration: underline;">not</strong> been approved yet. Visit <strong><a target="_blank" href="http://www.contoso.com">www.contoso.com</a></strong> for <strong>more</strong> information.</p>
</div> </div>
<div> <div>

View File

@ -41,7 +41,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId1">UserId1</label> <label class="control-label col-md-2" for="UserId1">UserId1</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId1&#39; is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/Aria/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId1&#x27; is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/Aria/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId1" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId1" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>
@ -49,7 +49,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId2">UserId2</label> <label class="control-label col-md-2" for="UserId2">UserId2</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId2&#39; is invalid." data-val-remote-additionalfields="*.UserId2" data-val-remote-type="Post" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId2" name="UserId2" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId2&#x27; is invalid." data-val-remote-additionalfields="*.UserId2" data-val-remote-type="Post" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId2" name="UserId2" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId2" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId2" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>
@ -65,7 +65,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId4">UserId4</label> <label class="control-label col-md-2" for="UserId4">UserId4</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId4&#39; is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId4&#x27; is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>

View File

@ -41,7 +41,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId1">UserId1</label> <label class="control-label col-md-2" for="UserId1">UserId1</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId1&#39; is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId1&#x27; is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId1" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId1" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>
@ -49,7 +49,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId2">UserId2</label> <label class="control-label col-md-2" for="UserId2">UserId2</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId2&#39; is invalid." data-val-remote-additionalfields="*.UserId2" data-val-remote-type="Post" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId2" name="UserId2" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId2&#x27; is invalid." data-val-remote-additionalfields="*.UserId2" data-val-remote-type="Post" data-val-remote-url="/RemoteAttribute_Verify/IsIdAvailable" id="UserId2" name="UserId2" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId2" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId2" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>
@ -65,7 +65,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label col-md-2" for="UserId4">UserId4</label> <label class="control-label col-md-2" for="UserId4">UserId4</label>
<div class="col-md-10"> <div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-remote="&#39;UserId4&#39; is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" /> <input class="form-control text-box single-line" data-val="true" data-val-remote="&#x27;UserId4&#x27; is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span> <span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span>
</div> </div>
</div> </div>

View File

@ -22,7 +22,7 @@ namespace Asp
private System.IO.TextWriter __tagHelperStringValueBuffer = null; private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414 #pragma warning restore 0414
private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext = null; private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext = null;
private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperRunner(); private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = null;
private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager = new Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperScopeManager(); private Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager = new Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperScopeManager();
private Microsoft.AspNet.Mvc.Razor.InputTestTagHelper __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = null; private Microsoft.AspNet.Mvc.Razor.InputTestTagHelper __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = null;
#line hidden #line hidden
@ -42,6 +42,7 @@ namespace Asp
#pragma warning disable 1998 #pragma warning disable 1998
public override async Task ExecuteAsync() public override async Task ExecuteAsync()
{ {
__tagHelperRunner = __tagHelperRunner ?? new Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelperRunner(HtmlEncoder);
BeginContext(120, 2, true); BeginContext(120, 2, true);
WriteLiteral("\r\n"); WriteLiteral("\r\n");
EndContext(); EndContext();

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -26,11 +27,14 @@ namespace Microsoft.AspNet.Mvc.Razor
var myService = new MyService(); var myService = new MyService();
var helper = Mock.Of<IHtmlHelper<object>>(); var helper = Mock.Of<IHtmlHelper<object>>();
var htmlEncoder = new HtmlEncoder();
var serviceProvider = new Mock<IServiceProvider>(); var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(MyService))) serviceProvider.Setup(p => p.GetService(typeof(MyService)))
.Returns(myService); .Returns(myService);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>))) serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>)))
.Returns(helper); .Returns(helper);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlEncoder)))
.Returns(htmlEncoder);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices) httpContext.SetupGet(c => c.RequestServices)
.Returns(serviceProvider.Object); .Returns(serviceProvider.Object);
@ -90,11 +94,14 @@ namespace Microsoft.AspNet.Mvc.Razor
var myService = new MyService(); var myService = new MyService();
var helper = Mock.Of<IHtmlHelper<object>>(); var helper = Mock.Of<IHtmlHelper<object>>();
var htmlEncoder = new HtmlEncoder();
var serviceProvider = new Mock<IServiceProvider>(); var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(MyService))) serviceProvider.Setup(p => p.GetService(typeof(MyService)))
.Returns(myService); .Returns(myService);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>))) serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>)))
.Returns(helper); .Returns(helper);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlEncoder)))
.Returns(htmlEncoder);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices) httpContext.SetupGet(c => c.RequestServices)
.Returns(serviceProvider.Object); .Returns(serviceProvider.Object);
@ -124,11 +131,14 @@ namespace Microsoft.AspNet.Mvc.Razor
var instance = new TestRazorPage(); var instance = new TestRazorPage();
var myService = new MyService(); var myService = new MyService();
var helper = Mock.Of<IHtmlHelper<object>>(); var helper = Mock.Of<IHtmlHelper<object>>();
var htmlEncoder = new HtmlEncoder();
var serviceProvider = new Mock<IServiceProvider>(); var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(MyService))) serviceProvider.Setup(p => p.GetService(typeof(MyService)))
.Returns(myService); .Returns(myService);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>))) serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>)))
.Returns(helper); .Returns(helper);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlEncoder)))
.Returns(htmlEncoder);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices) httpContext.SetupGet(c => c.RequestServices)
.Returns(serviceProvider.Object); .Returns(serviceProvider.Object);
@ -158,11 +168,14 @@ namespace Microsoft.AspNet.Mvc.Razor
var instance = new DoesNotDeriveFromRazorPageOfTButHasModelProperty(); var instance = new DoesNotDeriveFromRazorPageOfTButHasModelProperty();
var myService = new MyService(); var myService = new MyService();
var helper = Mock.Of<IHtmlHelper<object>>(); var helper = Mock.Of<IHtmlHelper<object>>();
var htmlEncoder = new HtmlEncoder();
var serviceProvider = new Mock<IServiceProvider>(); var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(p => p.GetService(typeof(MyService))) serviceProvider.Setup(p => p.GetService(typeof(MyService)))
.Returns(myService); .Returns(myService);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>))) serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper<object>)))
.Returns(helper); .Returns(helper);
serviceProvider.Setup(p => p.GetService(typeof(IHtmlEncoder)))
.Returns(htmlEncoder);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices) httpContext.SetupGet(c => c.RequestServices)
.Returns(serviceProvider.Object); .Returns(serviceProvider.Object);

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PageExecutionInstrumentation; using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -28,6 +29,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewContext = CreateViewContext(); var viewContext = CreateViewContext();
var page = CreatePage(v => var page = CreatePage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix"); v.Write("Hello Prefix");
v.StartWritingScope(); v.StartWritingScope();
v.Write("Hello from Output"); v.Write("Hello from Output");
@ -51,6 +53,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewContext = CreateViewContext(); var viewContext = CreateViewContext();
var page = CreatePage(v => var page = CreatePage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix"); v.Write("Hello Prefix");
v.StartWritingScope(); v.StartWritingScope();
v.Write("Hello In Scope"); v.Write("Hello In Scope");
@ -73,6 +76,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var viewContext = CreateViewContext(); var viewContext = CreateViewContext();
var page = CreatePage(v => var page = CreatePage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello Prefix"); v.Write("Hello Prefix");
v.StartWritingScope(); v.StartWritingScope();
v.Write("Hello In Scope Pre Nest"); v.Write("Hello In Scope Pre Nest");
@ -453,6 +457,7 @@ namespace Microsoft.AspNet.Mvc.Razor
.Verifiable(); .Verifiable();
var page = CreatePage(v => var page = CreatePage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Write(v.Href("url")); v.Write(v.Href("url"));
}); });
var services = new Mock<IServiceProvider>(); var services = new Mock<IServiceProvider>();
@ -554,6 +559,7 @@ namespace Microsoft.AspNet.Mvc.Razor
// Arrange // Arrange
var page = CreatePage(p => var page = CreatePage(p =>
{ {
p.HtmlEncoder = new HtmlEncoder();
p.WriteAttribute("href", p.WriteAttribute("href",
new PositionTagged<string>("prefix", 0), new PositionTagged<string>("prefix", 0),
new PositionTagged<string>("suffix", 34), new PositionTagged<string>("suffix", 34),

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http.Core; using Microsoft.AspNet.Http.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.PageExecutionInstrumentation; using Microsoft.AspNet.PageExecutionInstrumentation;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -30,6 +31,7 @@ namespace Microsoft.AspNet.Mvc.Razor
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
actual = v.Output; actual = v.Output;
v.HtmlEncoder = new HtmlEncoder();
v.Write("Hello world"); v.Write("Hello world");
}); });
var view = new RazorView(Mock.Of<IRazorViewEngine>(), var view = new RazorView(Mock.Of<IRazorViewEngine>(),
@ -165,17 +167,20 @@ namespace Microsoft.AspNet.Mvc.Razor
public async Task RenderAsync_AsPartial_ExecutesLayout_ButNotViewStartPages() public async Task RenderAsync_AsPartial_ExecutesLayout_ButNotViewStartPages()
{ {
// Arrange // Arrange
var expected = string.Join(Environment.NewLine, var htmlEncoder = new HtmlEncoder();
var expected = string.Join(htmlEncoder.HtmlEncode(Environment.NewLine),
"layout-content", "layout-content",
"page-content"); "page-content");
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Layout = LayoutPath; v.Layout = LayoutPath;
v.Write("page-content"); v.Write("page-content");
}); });
var layout = new TestableRazorPage(v => var layout = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-content" + Environment.NewLine); v.Write("layout-content" + Environment.NewLine);
v.RenderBodyPublic(); v.RenderBodyPublic();
}); });
@ -359,14 +364,19 @@ namespace Microsoft.AspNet.Mvc.Razor
public async Task RenderAsync_ExecutesLayoutPages() public async Task RenderAsync_ExecutesLayoutPages()
{ {
// Arrange // Arrange
var expected = var htmlEncoder = new HtmlEncoder();
@"layout-content var htmlEncodedNewLine = htmlEncoder.HtmlEncode(Environment.NewLine);
head-content var expected = "layout-content" +
body-content htmlEncodedNewLine +
foot-content"; "head-content" +
htmlEncodedNewLine +
"body-content" +
htmlEncodedNewLine +
"foot-content";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.WriteLiteral("body-content"); v.WriteLiteral("body-content");
v.Layout = LayoutPath; v.Layout = LayoutPath;
v.DefineSection("head", async writer => v.DefineSection("head", async writer =>
@ -380,6 +390,7 @@ foot-content";
}); });
var layout = new TestableRazorPage(v => var layout = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-content" + Environment.NewLine); v.Write("layout-content" + Environment.NewLine);
v.Write(v.RenderSection("head")); v.Write(v.RenderSection("head"));
v.Write(Environment.NewLine); v.Write(Environment.NewLine);
@ -475,15 +486,21 @@ foot-content";
public async Task RenderAsync_ExecutesNestedLayoutPages() public async Task RenderAsync_ExecutesNestedLayoutPages()
{ {
// Arrange // Arrange
var expected = var htmlEncoder = new HtmlEncoder();
@"layout-2 var htmlEncodedNewLine = htmlEncoder.HtmlEncode(Environment.NewLine);
bar-content var expected = "layout-2" +
layout-1 htmlEncodedNewLine +
foo-content "bar-content" +
body-content"; Environment.NewLine +
"layout-1" +
htmlEncodedNewLine +
"foo-content" +
Environment.NewLine +
"body-content";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.DefineSection("foo", async writer => v.DefineSection("foo", async writer =>
{ {
await writer.WriteLineAsync("foo-content"); await writer.WriteLineAsync("foo-content");
@ -493,6 +510,7 @@ body-content";
}); });
var layout1 = new TestableRazorPage(v => var layout1 = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-1" + Environment.NewLine); v.Write("layout-1" + Environment.NewLine);
v.Write(v.RenderSection("foo")); v.Write(v.RenderSection("foo"));
v.DefineSection("bar", writer => writer.WriteLineAsync("bar-content")); v.DefineSection("bar", writer => writer.WriteLineAsync("bar-content"));
@ -501,6 +519,7 @@ body-content";
}); });
var layout2 = new TestableRazorPage(v => var layout2 = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-2" + Environment.NewLine); v.Write("layout-2" + Environment.NewLine);
v.Write(v.RenderSection("bar")); v.Write(v.RenderSection("bar"));
v.RenderBodyPublic(); v.RenderBodyPublic();
@ -529,14 +548,18 @@ body-content";
public async Task RenderAsync_DoesNotCopyContentOnceRazorTextWriterIsNoLongerBuffering() public async Task RenderAsync_DoesNotCopyContentOnceRazorTextWriterIsNoLongerBuffering()
{ {
// Arrange // Arrange
var expected = var htmlEncoder = new HtmlEncoder();
@"layout-1 var expected = "layout-1" +
body content htmlEncoder.HtmlEncode(Environment.NewLine) +
section-content-1 "body content" +
section-content-2"; Environment.NewLine +
"section-content-1" +
Environment.NewLine +
"section-content-2";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Layout = "layout-1"; v.Layout = "layout-1";
v.WriteLiteral("body content" + Environment.NewLine); v.WriteLiteral("body content" + Environment.NewLine);
v.DefineSection("foo", async _ => v.DefineSection("foo", async _ =>
@ -549,6 +572,7 @@ section-content-2";
var layout1 = new TestableRazorPage(v => var layout1 = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-1" + Environment.NewLine); v.Write("layout-1" + Environment.NewLine);
v.RenderBodyPublic(); v.RenderBodyPublic();
v.Write(v.RenderSection("foo")); v.Write(v.RenderSection("foo"));
@ -576,13 +600,16 @@ section-content-2";
public async Task FlushAsync_DoesNotThrowWhenInvokedInsideOfASection() public async Task FlushAsync_DoesNotThrowWhenInvokedInsideOfASection()
{ {
// Arrange // Arrange
var expected = var htmlEncoder = new HtmlEncoder();
@"layout-1 var expected = "layout-1" +
section-content-1 htmlEncoder.HtmlEncode(Environment.NewLine) +
section-content-2"; "section-content-1" +
Environment.NewLine +
"section-content-2";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Layout = "layout-1"; v.Layout = "layout-1";
v.DefineSection("foo", async _ => v.DefineSection("foo", async _ =>
{ {
@ -594,6 +621,7 @@ section-content-2";
var layout1 = new TestableRazorPage(v => var layout1 = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = htmlEncoder;
v.Write("layout-1" + Environment.NewLine); v.Write("layout-1" + Environment.NewLine);
v.RenderBodyPublic(); v.RenderBodyPublic();
v.Write(v.RenderSection("foo")); v.Write(v.RenderSection("foo"));
@ -649,6 +677,7 @@ section-content-2";
var expected = @"A layout page cannot be rendered after 'FlushAsync' has been invoked."; var expected = @"A layout page cannot be rendered after 'FlushAsync' has been invoked.";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.DefineSection("foo", async writer => v.DefineSection("foo", async writer =>
{ {
writer.WriteLine("foo-content"); writer.WriteLine("foo-content");
@ -659,6 +688,7 @@ section-content-2";
}); });
var layoutPage = new TestableRazorPage(v => var layoutPage = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Write("layout-1" + Environment.NewLine); v.Write("layout-1" + Environment.NewLine);
v.Write(v.RenderSection("foo")); v.Write(v.RenderSection("foo"));
v.DefineSection("bar", writer => writer.WriteLineAsync("bar-content")); v.DefineSection("bar", writer => writer.WriteLineAsync("bar-content"));
@ -720,6 +750,7 @@ section-content-2";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
v.Layout = "Layout"; v.Layout = "Layout";
Assert.Same(pageWriter, v.Output); Assert.Same(pageWriter, v.Output);
Assert.Same(pageContext, v.PageExecutionContext); Assert.Same(pageContext, v.PageExecutionContext);
@ -728,6 +759,7 @@ section-content-2";
var layout = new TestableRazorPage(v => var layout = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
Assert.Same(layoutWriter, v.Output); Assert.Same(layoutWriter, v.Output);
Assert.Same(layoutContext, v.PageExecutionContext); Assert.Same(layoutContext, v.PageExecutionContext);
v.RenderBodyPublic(); v.RenderBodyPublic();
@ -779,6 +811,7 @@ section-content-2";
var page = new TestableRazorPage(v => var page = new TestableRazorPage(v =>
{ {
v.HtmlEncoder = new HtmlEncoder();
Assert.IsType<RazorTextWriter>(v.Output); Assert.IsType<RazorTextWriter>(v.Output);
Assert.Same(pageContext, v.PageExecutionContext); Assert.Same(pageContext, v.PageExecutionContext);
executed = true; executed = true;

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -41,7 +42,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "id", "myanchor" }, { "id", "myanchor" },
{ "asp-route-foo", "bar" }, { "asp-route-foo", "bar" },
}) },
htmlEncoder: new HtmlEncoder())
{ {
Content = "Something" Content = "Something"
}; };
@ -88,7 +90,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput( var output = new TagHelperOutput(
"a", "a",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
Content = string.Empty Content = string.Empty
}; };
@ -97,7 +100,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator generator
.Setup(mock => mock.GenerateRouteLink( .Setup(mock => mock.GenerateRouteLink(
string.Empty, "Default", "http", "contoso.com", "hello=world", null, null)) string.Empty, "Default", "http", "contoso.com", "hello=world", null, null))
.Returns(new TagBuilder("a")) .Returns(new TagBuilder("a", new HtmlEncoder()))
.Verifiable(); .Verifiable();
var anchorTagHelper = new AnchorTagHelper var anchorTagHelper = new AnchorTagHelper
{ {
@ -127,7 +130,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput( var output = new TagHelperOutput(
"a", "a",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
Content = string.Empty Content = string.Empty
}; };
@ -136,7 +140,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator generator
.Setup(mock => mock.GenerateActionLink( .Setup(mock => mock.GenerateActionLink(
string.Empty, "Index", "Home", "http", "contoso.com", "hello=world", null, null)) string.Empty, "Index", "Home", "http", "contoso.com", "hello=world", null, null))
.Returns(new TagBuilder("a")) .Returns(new TagBuilder("a", new HtmlEncoder()))
.Verifiable(); .Verifiable();
var anchorTagHelper = new AnchorTagHelper var anchorTagHelper = new AnchorTagHelper
{ {
@ -173,7 +177,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string>() attributes: new Dictionary<string, string>()
{ {
{ "href", "http://www.contoso.com" } { "href", "http://www.contoso.com" }
}); },
htmlEncoder: new HtmlEncoder());
if (propertyName == "asp-route-") if (propertyName == "asp-route-")
{ {
output.Attributes.Add("asp-route-foo", "bar"); output.Attributes.Add("asp-route-foo", "bar");
@ -208,7 +213,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home"); typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home");
var output = new TagHelperOutput( var output = new TagHelperOutput(
"a", "a",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var expectedErrorMessage = "Cannot determine an 'href' attribute for <a>. An <a> with a specified " + var expectedErrorMessage = "Cannot determine an 'href' attribute for <a>. An <a> with a specified " +
"'asp-route' must not have an 'asp-action' or 'asp-controller' attribute."; "'asp-route' must not have an 'asp-action' or 'asp-controller' attribute.";

View File

@ -17,6 +17,7 @@ using Microsoft.AspNet.Routing;
using Microsoft.Framework.Cache.Memory; using Microsoft.Framework.Cache.Memory;
using Microsoft.Framework.Cache.Memory.Infrastructure; using Microsoft.Framework.Cache.Memory.Infrastructure;
using Microsoft.Framework.Expiration.Interfaces; using Microsoft.Framework.Expiration.Interfaces;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -244,7 +245,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var childContent = "original-child-content"; var childContent = "original-child-content";
var cache = new MemoryCache(new MemoryCacheOptions()); var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext1 = GetTagHelperContext(id, childContent); var tagHelperContext1 = GetTagHelperContext(id, childContent);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string>()); var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string>(), new HtmlEncoder());
var cacheTagHelper1 = new CacheTagHelper var cacheTagHelper1 = new CacheTagHelper
{ {
VaryByQuery = "key1,key2", VaryByQuery = "key1,key2",
@ -265,7 +266,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2 // Arrange - 2
var tagHelperContext2 = GetTagHelperContext(id, "different-content"); var tagHelperContext2 = GetTagHelperContext(id, "different-content");
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string>()); var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string>(), new HtmlEncoder());
var cacheTagHelper2 = new CacheTagHelper var cacheTagHelper2 = new CacheTagHelper
{ {
VaryByQuery = "key1,key2", VaryByQuery = "key1,key2",
@ -293,7 +294,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var childContent1 = "original-child-content"; var childContent1 = "original-child-content";
var cache = new MemoryCache(new MemoryCacheOptions()); var cache = new MemoryCache(new MemoryCacheOptions());
var tagHelperContext1 = GetTagHelperContext(id, childContent1); var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -318,7 +321,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2 // Arrange - 2
var childContent2 = "different-content"; var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2); var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -529,7 +534,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime); .Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object }); var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1); var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -553,7 +560,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange - 2 // Arrange - 2
var childContent2 = "different-content"; var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2); var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -588,7 +597,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime); .Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object }); var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1); var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -613,7 +624,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
currentTime = currentTime.AddMinutes(5).AddSeconds(2); currentTime = currentTime.AddMinutes(5).AddSeconds(2);
var childContent2 = "different-content"; var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2); var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -647,7 +660,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(() => currentTime); .Returns(() => currentTime);
var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object }); var cache = new MemoryCache(new MemoryCacheOptions { Clock = clock.Object });
var tagHelperContext1 = GetTagHelperContext(id, childContent1); var tagHelperContext1 = GetTagHelperContext(id, childContent1);
var tagHelperOutput1 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput1 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -672,7 +687,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
currentTime = currentTime.AddSeconds(35); currentTime = currentTime.AddSeconds(35);
var childContent2 = "different-content"; var childContent2 = "different-content";
var tagHelperContext2 = GetTagHelperContext(id, childContent2); var tagHelperContext2 = GetTagHelperContext(id, childContent2);
var tagHelperOutput2 = new TagHelperOutput("cache", new Dictionary<string, string> { { "attr", "value" } }) var tagHelperOutput2 = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"
@ -716,7 +733,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}); });
return Task.FromResult(expectedContent); return Task.FromResult(expectedContent);
}); });
var tagHelperOutput = new TagHelperOutput("cache", new Dictionary<string, string>()) var tagHelperOutput = new TagHelperOutput("cache",
new Dictionary<string, string> { { "attr", "value" } },
new HtmlEncoder())
{ {
PreContent = "<cache>", PreContent = "<cache>",
PostContent = "</cache>" PostContent = "</cache>"

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -145,7 +146,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers.Test
{ {
attributes = attributes ?? new Dictionary<string, string>(); attributes = attributes ?? new Dictionary<string, string>();
return new TagHelperOutput(tagName, attributes); return new TagHelperOutput(tagName, attributes, new HtmlEncoder());
} }
} }
} }

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -42,7 +43,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "id", "myform" }, { "id", "myform" },
{ "asp-route-foo", "bar" }, { "asp-route-foo", "bar" },
}) },
htmlEncoder: new HtmlEncoder())
{ {
PostContent = "Something" PostContent = "Something"
}; };
@ -98,7 +100,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput( var output = new TagHelperOutput(
"form", "form",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
generator generator
.Setup(mock => mock.GenerateForm( .Setup(mock => mock.GenerateForm(
@ -108,10 +111,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
It.IsAny<object>(), It.IsAny<object>(),
It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<object>())) It.IsAny<object>()))
.Returns(new TagBuilder("form")); .Returns(new TagBuilder("form", new HtmlEncoder()));
generator.Setup(mock => mock.GenerateAntiForgery(viewContext)) generator.Setup(mock => mock.GenerateAntiForgery(viewContext))
.Returns(new TagBuilder("input")); .Returns(new TagBuilder("input", new HtmlEncoder()));
var formTagHelper = new FormTagHelper var formTagHelper = new FormTagHelper
{ {
Action = "Index", Action = "Index",
@ -149,7 +152,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "asp-route-val", "hello" }, { "asp-route-val", "hello" },
{ "asp-roUte--Foo", "bar" } { "asp-roUte--Foo", "bar" }
}); },
htmlEncoder: new HtmlEncoder());
output.Attributes.Add(expectedAttribute); output.Attributes.Add(expectedAttribute);
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
@ -175,7 +179,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
routeValue = Assert.Single(routeValueDictionary, kvp => kvp.Key.Equals("-Foo")); routeValue = Assert.Single(routeValueDictionary, kvp => kvp.Key.Equals("-Foo"));
Assert.Equal("bar", routeValue.Value); Assert.Equal("bar", routeValue.Value);
}) })
.Returns(new TagBuilder("form")) .Returns(new TagBuilder("form", new HtmlEncoder()))
.Verifiable(); .Verifiable();
var formTagHelper = new FormTagHelper var formTagHelper = new FormTagHelper
{ {
@ -210,11 +214,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput( var output = new TagHelperOutput(
"form", "form",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
generator generator
.Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, "POST", null)) .Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, "POST", null))
.Returns(new TagBuilder("form")) .Returns(new TagBuilder("form", new HtmlEncoder()))
.Verifiable(); .Verifiable();
var formTagHelper = new FormTagHelper var formTagHelper = new FormTagHelper
{ {
@ -253,7 +258,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string> attributes: new Dictionary<string, string>
{ {
{ "aCTiON", htmlAction }, { "aCTiON", htmlAction },
}); },
htmlEncoder: new HtmlEncoder());
var context = new TagHelperContext( var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>() allAttributes: new Dictionary<string, object>()
@ -292,7 +298,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var generator = new Mock<IHtmlGenerator>(); var generator = new Mock<IHtmlGenerator>();
generator.Setup(mock => mock.GenerateAntiForgery(It.IsAny<ViewContext>())) generator.Setup(mock => mock.GenerateAntiForgery(It.IsAny<ViewContext>()))
.Returns(new TagBuilder("input")); .Returns(new TagBuilder("input", new HtmlEncoder()));
var formTagHelper = new FormTagHelper var formTagHelper = new FormTagHelper
{ {
AntiForgery = antiForgery, AntiForgery = antiForgery,
@ -304,7 +310,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string> attributes: new Dictionary<string, string>
{ {
{ "aCTiON", "my-action" }, { "aCTiON", "my-action" },
}); },
htmlEncoder: new HtmlEncoder());
var context = new TagHelperContext( var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(), allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
@ -341,7 +348,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string> attributes: new Dictionary<string, string>
{ {
{ "action", "my-action" }, { "action", "my-action" },
}); },
htmlEncoder: new HtmlEncoder());
if (propertyName == "asp-route-") if (propertyName == "asp-route-")
{ {
tagHelperOutput.Attributes.Add("asp-route-foo", "bar"); tagHelperOutput.Attributes.Add("asp-route-foo", "bar");

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -103,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -159,7 +160,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(originalTagName, originalAttributes) var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = originalContent, Content = originalContent,
@ -169,7 +170,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict); var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar)); var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar));
var tagBuilder = new TagBuilder("input") var tagBuilder = new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -190,7 +191,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.ViewContext, tagHelper.ViewContext,
tagHelper.For.ModelExplorer, tagHelper.For.ModelExplorer,
tagHelper.For.Name)) tagHelper.For.Name))
.Returns(new TagBuilder("hidden")) .Returns(new TagBuilder("hidden", new HtmlEncoder()))
.Verifiable(); .Verifiable();
// Act // Act
@ -250,7 +251,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -263,7 +264,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.For.Metadata.DataTypeName = dataTypeName; tagHelper.For.Metadata.DataTypeName = dataTypeName;
tagHelper.InputTypeName = inputTypeName; tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input") var tagBuilder = new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -338,7 +339,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -351,7 +352,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.For.Metadata.DataTypeName = dataTypeName; tagHelper.For.Metadata.DataTypeName = dataTypeName;
tagHelper.InputTypeName = inputTypeName; tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input") var tagBuilder = new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -423,7 +424,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -436,7 +437,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.InputTypeName = inputTypeName; tagHelper.InputTypeName = inputTypeName;
tagHelper.Value = value; tagHelper.Value = value;
var tagBuilder = new TagBuilder("input") var tagBuilder = new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -523,7 +524,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -536,7 +537,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagHelper.For.Metadata.DataTypeName = dataTypeName; tagHelper.For.Metadata.DataTypeName = dataTypeName;
tagHelper.InputTypeName = inputTypeName; tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input") var tagBuilder = new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -588,7 +589,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, expectedAttributes) var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -644,7 +645,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes); var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var tagHelper = new InputTagHelper var tagHelper = new InputTagHelper
{ {
Format = "{0}", Format = "{0}",

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.TagHelpers namespace Microsoft.AspNet.Mvc.TagHelpers
@ -194,7 +195,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, htmlAttributes) var output = new TagHelperOutput(expectedTagName, htmlAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
PostContent = expectedPostContent, PostContent = expectedPostContent,
@ -250,7 +251,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, expectedAttributes) var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,

View File

@ -15,6 +15,7 @@ using Microsoft.AspNet.Mvc.TagHelpers.Internal;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -100,6 +101,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = MakeViewContext(); var viewContext = MakeViewContext();
var helper = new LinkTagHelper var helper = new LinkTagHelper
{ {
HtmlEncoder = new HtmlEncoder(),
Logger = logger.Object, Logger = logger.Object,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
ViewContext = viewContext, ViewContext = viewContext,
@ -142,6 +144,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = MakeViewContext(); var viewContext = MakeViewContext();
var helper = new LinkTagHelper var helper = new LinkTagHelper
{ {
HtmlEncoder = new HtmlEncoder(),
Logger = logger.Object, Logger = logger.Object,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
ViewContext = viewContext, ViewContext = viewContext,
@ -306,6 +309,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Returns(new[] { "/css/site.css", "/base.css" }); .Returns(new[] { "/css/site.css", "/base.css" });
var helper = new LinkTagHelper var helper = new LinkTagHelper
{ {
HtmlEncoder = new HtmlEncoder(),
GlobbingUrlBuilder = globbingUrlBuilder.Object, GlobbingUrlBuilder = globbingUrlBuilder.Object,
Logger = logger.Object, Logger = logger.Object,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
@ -321,6 +325,46 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"<link href=\"/base.css\" rel=\"stylesheet\" />", output.Content); "<link href=\"/base.css\" rel=\"stylesheet\" />", output.Content);
} }
[Fact]
public void RendersLinkTagsForGlobbedHrefResults_UsingProvidedEncoder()
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
{
["href"] = "/css/site.css",
["rel"] = "stylesheet",
["asp-href-include"] = "**/*.css"
});
var output = MakeTagHelperOutput("link", attributes: new Dictionary<string, string>
{
["href"] = "/css/site.css",
["rel"] = "stylesheet"
});
var logger = new Mock<ILogger<LinkTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>();
globbingUrlBuilder.Setup(g => g.BuildUrlList("/css/site.css", "**/*.css", null))
.Returns(new[] { "/css/site.css", "/base.css" });
var helper = new LinkTagHelper
{
HtmlEncoder = new TestHtmlEncoder(),
GlobbingUrlBuilder = globbingUrlBuilder.Object,
Logger = logger.Object,
HostingEnvironment = hostingEnvironment,
ViewContext = viewContext,
HrefInclude = "**/*.css"
};
// Act
helper.Process(context, output);
// Assert
Assert.Equal("<link href=\"HtmlEncode[[/css/site.css]]\" rel=\"stylesheet\" />" +
"<link href=\"HtmlEncode[[/base.css]]\" rel=\"stylesheet\" />", output.Content);
}
private static ViewContext MakeViewContext() private static ViewContext MakeViewContext()
{ {
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor()); var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
@ -348,7 +392,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
attributes = attributes ?? new Dictionary<string, string>(); attributes = attributes ?? new Dictionary<string, string>();
return new TagHelperOutput(tagName, attributes); return new TagHelperOutput(tagName, attributes, new HtmlEncoder());
} }
private static IHostingEnvironment MakeHostingEnvironment() private static IHostingEnvironment MakeHostingEnvironment()
@ -364,5 +408,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
return hostingEnvironment.Object; return hostingEnvironment.Object;
} }
private class TestHtmlEncoder : 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

@ -6,6 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.TagHelpers namespace Microsoft.AspNet.Mvc.TagHelpers
@ -141,7 +142,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent)); getChildContentAsync: () => Task.FromResult(originalContent));
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
Content = originalContent, Content = originalContent,
SelfClosing = false, SelfClosing = false,
@ -200,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent)); getChildContentAsync: () => Task.FromResult(originalContent));
var output = new TagHelperOutput(originalTagName, originalAttributes) var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = originalPreContent, PreContent = originalPreContent,
Content = originalContent, Content = originalContent,
@ -256,7 +257,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult(originalContent)); getChildContentAsync: () => Task.FromResult(originalContent));
var output = new TagHelperOutput(originalTagName, originalAttributes) var output = new TagHelperOutput(originalTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = originalPreContent, PreContent = originalPreContent,
Content = originalContent, Content = originalContent,

View File

@ -15,6 +15,7 @@ using Microsoft.AspNet.Mvc.TagHelpers.Internal;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -120,6 +121,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = MakeViewContext(); var viewContext = MakeViewContext();
var helper = new ScriptTagHelper var helper = new ScriptTagHelper
{ {
HtmlEncoder = new HtmlEncoder(),
Logger = logger, Logger = logger,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
ViewContext = viewContext, ViewContext = viewContext,
@ -346,6 +348,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var helper = new ScriptTagHelper var helper = new ScriptTagHelper
{ {
HtmlEncoder = new HtmlEncoder(),
Logger = logger, Logger = logger,
ViewContext = viewContext, ViewContext = viewContext,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
@ -387,7 +390,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Logger = logger.Object, Logger = logger.Object,
HostingEnvironment = hostingEnvironment, HostingEnvironment = hostingEnvironment,
ViewContext = viewContext, ViewContext = viewContext,
SrcInclude = "**/*.js" SrcInclude = "**/*.js",
HtmlEncoder = new HtmlEncoder()
}; };
// Act // Act
@ -397,6 +401,44 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Assert.Equal("<script src=\"/js/site.js\"></script><script src=\"/common.js\"></script>", output.Content); Assert.Equal("<script src=\"/js/site.js\"></script><script src=\"/common.js\"></script>", output.Content);
} }
[Fact]
public async Task RendersScriptTagsForGlobbedSrcResults_UsesProvidedEncoder()
{
// Arrange
var context = MakeTagHelperContext(
attributes: new Dictionary<string, object>
{
["src"] = "/js/site.js",
["asp-src-include"] = "**/*.js"
});
var output = MakeTagHelperOutput("script", attributes: new Dictionary<string, string>
{
["src"] = "/js/site.js"
});
var logger = new Mock<ILogger<ScriptTagHelper>>();
var hostingEnvironment = MakeHostingEnvironment();
var viewContext = MakeViewContext();
var globbingUrlBuilder = new Mock<GlobbingUrlBuilder>();
globbingUrlBuilder.Setup(g => g.BuildUrlList("/js/site.js", "**/*.js", null))
.Returns(new[] { "/js/site.js", "/common.js" });
var helper = new ScriptTagHelper
{
GlobbingUrlBuilder = globbingUrlBuilder.Object,
Logger = logger.Object,
HostingEnvironment = hostingEnvironment,
ViewContext = viewContext,
SrcInclude = "**/*.js",
HtmlEncoder = new TestHtmlEncoder()
};
// Act
await helper.ProcessAsync(context, output);
// Assert
Assert.Equal("<script src=\"HtmlEncode[[/js/site.js]]\"></script>" +
"<script src=\"HtmlEncode[[/common.js]]\"></script>", output.Content);
}
private TagHelperContext MakeTagHelperContext( private TagHelperContext MakeTagHelperContext(
IDictionary<string, object> attributes = null, IDictionary<string, object> attributes = null,
string content = null) string content = null)
@ -424,7 +466,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
attributes = attributes ?? new Dictionary<string, string>(); attributes = attributes ?? new Dictionary<string, string>();
return new TagHelperOutput(tagName, attributes); return new TagHelperOutput(tagName, attributes, new HtmlEncoder());
} }
private TagHelperLogger<ScriptTagHelper> CreateLogger() private TagHelperLogger<ScriptTagHelper> CreateLogger()
@ -445,5 +487,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
return hostingEnvironment.Object; return hostingEnvironment.Object;
} }
private class TestHtmlEncoder : 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

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -202,7 +203,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -287,7 +288,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -386,7 +387,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes) var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -470,7 +471,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes); var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var metadataProvider = new EmptyModelMetadataProvider(); var metadataProvider = new EmptyModelMetadataProvider();
string model = null; string model = null;
@ -536,7 +537,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(tagName, originalAttributes); var output = new TagHelperOutput(tagName, originalAttributes, new HtmlEncoder());
var metadataProvider = new EmptyModelMetadataProvider(); var metadataProvider = new EmptyModelMetadataProvider();
var modelExplorer = metadataProvider.GetModelExplorerForType(modelType, model); var modelExplorer = metadataProvider.GetModelExplorerForType(modelType, model);
@ -592,7 +593,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, originalAttributes); var output = new TagHelperOutput(expectedTagName, originalAttributes, new HtmlEncoder());
var tagHelper = new SelectTagHelper var tagHelper = new SelectTagHelper
{ {
Items = Enumerable.Empty<SelectListItem>(), Items = Enumerable.Empty<SelectListItem>(),

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.TagHelpers namespace Microsoft.AspNet.Mvc.TagHelpers
@ -20,7 +21,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var tagHelperContext = new TagHelperContext( var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal) allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
{ {
@ -49,7 +51,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string>() attributes: new Dictionary<string, string>()
{ {
{ attributeName, "world2" } { attributeName, "world2" }
}); },
htmlEncoder: new HtmlEncoder());
var expectedAttribute = new KeyValuePair<string, string>(attributeName, "world2"); var expectedAttribute = new KeyValuePair<string, string>(attributeName, "world2");
var tagHelperContext = new TagHelperContext( var tagHelperContext = new TagHelperContext(
allAttributes: new Dictionary<string, object>(StringComparer.Ordinal) allAttributes: new Dictionary<string, object>(StringComparer.Ordinal)
@ -78,7 +81,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "route-Hello", "World" }, { "route-Hello", "World" },
{ "Route-I", "Am" } { "Route-I", "Am" }
}); },
htmlEncoder: new HtmlEncoder());
var expectedAttribute = new KeyValuePair<string, string>("type", "btn"); var expectedAttribute = new KeyValuePair<string, string>("type", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute); tagHelperOutput.Attributes.Add(expectedAttribute);
var attributes = tagHelperOutput.FindPrefixedAttributes("route-"); var attributes = tagHelperOutput.FindPrefixedAttributes("route-");
@ -101,7 +105,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "routeHello", "World" }, { "routeHello", "World" },
{ "Routee-I", "Am" } { "Routee-I", "Am" }
}); },
htmlEncoder: new HtmlEncoder());
// Act // Act
var attributes = tagHelperOutput.FindPrefixedAttributes("route-"); var attributes = tagHelperOutput.FindPrefixedAttributes("route-");
@ -120,11 +125,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var expectedAttribute = new KeyValuePair<string, string>("type", "btn"); var expectedAttribute = new KeyValuePair<string, string>("type", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute); tagHelperOutput.Attributes.Add(expectedAttribute);
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add("type", "hello"); tagBuilder.Attributes.Add("type", "hello");
// Act // Act
@ -141,10 +147,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
tagHelperOutput.Attributes.Add("class", "Hello"); tagHelperOutput.Attributes.Add("class", "Hello");
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add("class", "btn"); tagBuilder.Attributes.Add("class", "btn");
var expectedAttribute = new KeyValuePair<string, string>("class", "Hello btn"); var expectedAttribute = new KeyValuePair<string, string>("class", "Hello btn");
@ -167,10 +174,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
tagHelperOutput.Attributes.Add(originalName, "Hello"); tagHelperOutput.Attributes.Add(originalName, "Hello");
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
tagBuilder.Attributes.Add(updateName, "btn"); tagBuilder.Attributes.Add(updateName, "btn");
// Act // Act
@ -187,9 +195,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
var expectedAttribute = new KeyValuePair<string, string>("visible", "val < 3"); var expectedAttribute = new KeyValuePair<string, string>("visible", "val < 3");
tagBuilder.Attributes.Add(expectedAttribute); tagBuilder.Attributes.Add(expectedAttribute);
@ -207,9 +216,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
var expectedAttribute1 = new KeyValuePair<string, string>("class", "btn"); var expectedAttribute1 = new KeyValuePair<string, string>("class", "btn");
var expectedAttribute2 = new KeyValuePair<string, string>("class2", "btn"); var expectedAttribute2 = new KeyValuePair<string, string>("class2", "btn");
tagBuilder.Attributes.Add(expectedAttribute1); tagBuilder.Attributes.Add(expectedAttribute1);
@ -232,11 +242,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var expectedAttribute = new KeyValuePair<string, string>("class", "btn"); var expectedAttribute = new KeyValuePair<string, string>("class", "btn");
tagHelperOutput.Attributes.Add(expectedAttribute); tagHelperOutput.Attributes.Add(expectedAttribute);
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
// Act // Act
tagHelperOutput.MergeAttributes(tagBuilder); tagHelperOutput.MergeAttributes(tagBuilder);
@ -252,11 +263,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Arrange // Arrange
var tagHelperOutput = new TagHelperOutput( var tagHelperOutput = new TagHelperOutput(
"p", "p",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var expectedOutputAttribute = new KeyValuePair<string, string>("class", "btn"); var expectedOutputAttribute = new KeyValuePair<string, string>("class", "btn");
tagHelperOutput.Attributes.Add(expectedOutputAttribute); tagHelperOutput.Attributes.Add(expectedOutputAttribute);
var tagBuilder = new TagBuilder("p"); var tagBuilder = new TagBuilder("p", new HtmlEncoder());
var expectedBuilderAttribute = new KeyValuePair<string, string>("for", "hello"); var expectedBuilderAttribute = new KeyValuePair<string, string>("for", "hello");
tagBuilder.Attributes.Add(expectedBuilderAttribute); tagBuilder.Attributes.Add(expectedBuilderAttribute);

View File

@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
namespace Microsoft.AspNet.Mvc.TagHelpers namespace Microsoft.AspNet.Mvc.TagHelpers
@ -38,7 +39,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
IScopedInstance<ActionBindingContext> bindingContextAccessor, IScopedInstance<ActionBindingContext> bindingContextAccessor,
IUrlHelper urlHelper, IUrlHelper urlHelper,
IDictionary<string, object> validationAttributes) IDictionary<string, object> validationAttributes)
: base(GetAntiForgery(), bindingContextAccessor, metadataProvider, urlHelper) : base(GetAntiForgery(), bindingContextAccessor, metadataProvider, urlHelper, new HtmlEncoder())
{ {
_validationAttributes = validationAttributes; _validationAttributes = validationAttributes;
} }
@ -65,7 +66,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
public override TagBuilder GenerateAntiForgery(ViewContext viewContext) public override TagBuilder GenerateAntiForgery(ViewContext viewContext)
{ {
return new TagBuilder("input") return new TagBuilder("input", new HtmlEncoder())
{ {
Attributes = Attributes =
{ {
@ -95,7 +96,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Mock.Of<IClaimUidExtractor>(), Mock.Of<IClaimUidExtractor>(),
Mock.Of<IDataProtectionProvider>(), Mock.Of<IDataProtectionProvider>(),
Mock.Of<IAntiForgeryAdditionalDataProvider>(), Mock.Of<IAntiForgeryAdditionalDataProvider>(),
optionsAccessor.Object); optionsAccessor.Object,
new HtmlEncoder());
return antiForgery; return antiForgery;
} }

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.Framework.WebEncoders;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.TagHelpers namespace Microsoft.AspNet.Mvc.TagHelpers
@ -121,7 +122,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ {
{ "class", "form-control" }, { "class", "form-control" },
}; };
var output = new TagHelperOutput(expectedTagName, htmlAttributes) var output = new TagHelperOutput(expectedTagName, htmlAttributes, new HtmlEncoder())
{ {
Content = "original content", Content = "original content",
SelfClosing = true, SelfClosing = true,
@ -174,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput(expectedTagName, expectedAttributes) var output = new TagHelperOutput(expectedTagName, expectedAttributes, new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -46,7 +47,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string> attributes: new Dictionary<string, string>
{ {
{ "id", "myvalidationmessage" } { "id", "myvalidationmessage" }
}) },
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -96,7 +98,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
getChildContentAsync: () => Task.FromResult("Something")); getChildContentAsync: () => Task.FromResult("Something"));
var output = new TagHelperOutput( var output = new TagHelperOutput(
"span", "span",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -107,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator generator
.Setup(mock => .Setup(mock =>
mock.GenerateValidationMessage(expectedViewContext, "Hello", null, null, null)) mock.GenerateValidationMessage(expectedViewContext, "Hello", null, null, null))
.Returns(new TagBuilder("span")) .Returns(new TagBuilder("span", new HtmlEncoder()))
.Verifiable(); .Verifiable();
validationMessageTagHelper.Generator = generator.Object; validationMessageTagHelper.Generator = generator.Object;
validationMessageTagHelper.ViewContext = expectedViewContext; validationMessageTagHelper.ViewContext = expectedViewContext;
@ -137,7 +140,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}; };
var output = new TagHelperOutput( var output = new TagHelperOutput(
"span", "span",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
Content = outputContent Content = outputContent
}; };
@ -147,7 +151,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult(childContent)); getChildContentAsync: () => Task.FromResult(childContent));
var tagBuilder = new TagBuilder("span2") var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{ {
InnerHtml = "New HTML" InnerHtml = "New HTML"
}; };
@ -193,14 +197,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}; };
var output = new TagHelperOutput( var output = new TagHelperOutput(
"span", "span",
attributes: new Dictionary<string, string>()); attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder());
var context = new TagHelperContext( var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(), allAttributes: new Dictionary<string, object>(),
items: new Dictionary<object, object>(), items: new Dictionary<object, object>(),
uniqueId: "test", uniqueId: "test",
getChildContentAsync: () => Task.FromResult(childContent)); getChildContentAsync: () => Task.FromResult(childContent));
var tagBuilder = new TagBuilder("span2") var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{ {
InnerHtml = "New HTML" InnerHtml = "New HTML"
}; };
@ -243,7 +248,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content"; var expectedPostContent = "original post-content";
var output = new TagHelperOutput( var output = new TagHelperOutput(
"span", "span",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,

View File

@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Microsoft.Framework.WebEncoders;
using Moq; using Moq;
using Xunit; using Xunit;
@ -52,7 +53,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
attributes: new Dictionary<string, string> attributes: new Dictionary<string, string>
{ {
{ "class", "form-control" } { "class", "form-control" }
}) },
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -98,7 +100,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content"; var expectedPostContent = "original post-content";
var output = new TagHelperOutput( var output = new TagHelperOutput(
"div", "div",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -113,7 +116,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
null, // message null, // message
null, // headerTag null, // headerTag
null)) // htmlAttributes null)) // htmlAttributes
.Returns(new TagBuilder("div")) .Returns(new TagBuilder("div", new HtmlEncoder()))
.Verifiable(); .Verifiable();
validationSummaryTagHelper.ViewContext = expectedViewContext; validationSummaryTagHelper.ViewContext = expectedViewContext;
validationSummaryTagHelper.Generator = generator.Object; validationSummaryTagHelper.Generator = generator.Object;
@ -141,13 +144,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedContent = "original content"; var expectedContent = "original content";
var output = new TagHelperOutput( var output = new TagHelperOutput(
"div", "div",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
PostContent = "Content of validation summary" PostContent = "Content of validation summary"
}; };
var tagBuilder = new TagBuilder("span2") var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{ {
InnerHtml = "New HTML" InnerHtml = "New HTML"
}; };
@ -199,7 +203,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedPostContent = "original post-content"; var expectedPostContent = "original post-content";
var output = new TagHelperOutput( var output = new TagHelperOutput(
"div", "div",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
@ -236,13 +241,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedContent = "original content"; var expectedContent = "original content";
var output = new TagHelperOutput( var output = new TagHelperOutput(
"div", "div",
attributes: new Dictionary<string, string>()) attributes: new Dictionary<string, string>(),
htmlEncoder: new HtmlEncoder())
{ {
PreContent = expectedPreContent, PreContent = expectedPreContent,
Content = expectedContent, Content = expectedContent,
PostContent = "Content of validation message", PostContent = "Content of validation message",
}; };
var tagBuilder = new TagBuilder("span2") var tagBuilder = new TagBuilder("span2", new HtmlEncoder())
{ {
InnerHtml = "New HTML" InnerHtml = "New HTML"
}; };

View File

@ -19,7 +19,7 @@ namespace ActivatorWebSite.TagHelpers
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
var builder = new TagBuilder("h2"); var builder = new TagBuilder("h2", HtmlHelper.HtmlEncoder);
var title = ViewContext.ViewBag.Title; var title = ViewContext.ViewBag.Title;
builder.InnerHtml = HtmlHelper.Encode(title); builder.InnerHtml = HtmlHelper.Encode(title);
output.PreContent = builder.ToString(); output.PreContent = builder.ToString();

View File

@ -14,16 +14,11 @@ namespace TagHelpersWebSite.TagHelpers
private static readonly Dictionary<string, string> PrettyTagStyles = private static readonly Dictionary<string, string> PrettyTagStyles =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{ {
{ "a", @"background-color: gray; { "a", "background-color: gray;color: white;border-radius: 3px;"
color: white; + "border: 1px solid black;padding: 3px;font-family: cursive;" },
border-radius: 3px; { "strong", "font-size: 1.25em;text-decoration: underline;" },
border: 1px solid black; { "h1", "font-family: cursive;" },
padding: 3px; { "h3", "font-family: cursive;" }
font-family: cursive;" },
{ "strong", @"font-size: 1.25em;
text-decoration: underline;" },
{ "h1", @"font-family: cursive;" },
{ "h3", @"font-family: cursive;" }
}; };
public bool? MakePretty { get; set; } public bool? MakePretty { get; set; }