Make HTML helper `null` handling consistent

- #874 lines 3, 4, and 6
- correct `Value()` to treat a `null` expression name the same as `string.Empty`
- add missing `[NotNull]` attributes in `EditorExtensions` and for `GenerateIdFromName()`
- consistently pass `null` for default expression names to the helpers
 - for example, from extension methods
- add test cases using `null` for expression name

nits:
- correct summary XML comment for `HtmlHelper` class
- use named parameters and prefer interface (not extension) methods in changed calls
- use `string.Empty` instead of `""` in a few tests
This commit is contained in:
dougbu 2014-08-05 09:14:30 -07:00
parent 4bf078269f
commit 56d66c090e
15 changed files with 95 additions and 85 deletions

View File

@ -13,6 +13,6 @@
}
@Html.TextBox(
name: string.Empty,
name: null,
value: FormattedValue,
htmlAttributes: new { @class = "text-box single-line", style = "font-weight: bold", })

View File

@ -32,15 +32,20 @@ namespace Microsoft.AspNet.Mvc.Rendering
private static string BooleanTemplateCheckbox(IHtmlHelper html, bool value)
{
return html.CheckBox(string.Empty, value, CreateHtmlAttributes(html, "check-box")).ToString();
return html.CheckBox(
name: null,
isChecked: value,
htmlAttributes: CreateHtmlAttributes(html, "check-box"))
.ToString();
}
private static string BooleanTemplateDropDownList(IHtmlHelper html, bool? value)
{
return html.DropDownList(
string.Empty,
DefaultDisplayTemplates.TriStateValues(value),
CreateHtmlAttributes(html, "list-box tri-state"))
name: null,
selectList: DefaultDisplayTemplates.TriStateValues(value),
optionLabel: null,
htmlAttributes: CreateHtmlAttributes(html, "list-box tri-state"))
.ToString();
}
@ -144,7 +149,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
var htmlAttributesObject = viewData[HtmlAttributeKey];
var hiddenResult = html.Hidden(string.Empty, model, htmlAttributesObject);
var hiddenResult = html.Hidden(name: null, value: model, htmlAttributes: htmlAttributesObject);
result += hiddenResult.ToString();
return result;
@ -262,9 +267,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
public static string PasswordTemplate(IHtmlHelper html)
{
return html.Password(string.Empty,
html.ViewData.TemplateInfo.FormattedModelValue,
CreateHtmlAttributes(html, "text-box single-line password"))
return html.Password(
name: null,
value: html.ViewData.TemplateInfo.FormattedModelValue,
htmlAttributes: CreateHtmlAttributes(html, "text-box single-line password"))
.ToString();
}
@ -356,8 +362,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
private static string GenerateTextBox(IHtmlHelper html, string inputType, object value)
{
return html.TextBox(
name: string.Empty,
name: null,
value: value,
format: null,
htmlAttributes: CreateHtmlAttributes(html, className: "text-box single-line", inputType: inputType))
.ToString();
}

View File

@ -18,7 +18,7 @@ using Microsoft.AspNet.Mvc.Rendering.Expressions;
namespace Microsoft.AspNet.Mvc.Rendering
{
/// <summary>
/// Default implementation of non-generic portions of <see cref="IHtmlHelper{TModel}"/>.
/// Default implementation of <see cref="IHtmlHelper">.
/// </summary>
public class HtmlHelper : IHtmlHelper, ICanHasViewContext
{
@ -482,7 +482,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
/// <inheritdoc />
public string Value([NotNull] string name, string format)
public string Value(string name, string format)
{
return GenerateValue(name, value: null, format: format, useViewData: true);
}
@ -1275,7 +1275,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
else if (useViewData)
{
if (name.Length == 0)
if (string.IsNullOrEmpty(name))
{
// case 2(a): format the value from ModelMetadata for the current model
var metadata = ViewData.ModelMetadata;

View File

@ -90,19 +90,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
public static HtmlString DisplayForModel([NotNull] this IHtmlHelper html)
{
return html.Display(expression: string.Empty, templateName: null, htmlFieldName: null,
additionalViewData: null);
return html.Display(expression: null, templateName: null, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString DisplayForModel([NotNull] this IHtmlHelper html, object additionalViewData)
{
return html.Display(expression: string.Empty, templateName: null, htmlFieldName: null,
return html.Display(expression: null, templateName: null, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString DisplayForModel([NotNull] this IHtmlHelper html, string templateName)
{
return html.Display(expression: string.Empty, templateName: templateName, htmlFieldName: null,
return html.Display(expression: null, templateName: templateName, htmlFieldName: null,
additionalViewData: null);
}
@ -111,7 +110,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string templateName,
object additionalViewData)
{
return html.Display(expression: string.Empty, templateName: templateName, htmlFieldName: null,
return html.Display(expression: null, templateName: templateName, htmlFieldName: null,
additionalViewData: additionalViewData);
}
@ -120,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string templateName,
string htmlFieldName)
{
return html.Display(expression: string.Empty, templateName: templateName, htmlFieldName: htmlFieldName,
return html.Display(expression: null, templateName: templateName, htmlFieldName: htmlFieldName,
additionalViewData: null);
}
@ -130,7 +129,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string htmlFieldName,
object additionalViewData)
{
return html.Display(expression: string.Empty, templateName: templateName, htmlFieldName: htmlFieldName,
return html.Display(expression: null, templateName: templateName, htmlFieldName: htmlFieldName,
additionalViewData: additionalViewData);
}
}

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <returns>A <see cref="String"/> containing the display name.</returns>
public static string DisplayNameForModel([NotNull] this IHtmlHelper htmlHelper)
{
return htmlHelper.DisplayName(string.Empty);
return htmlHelper.DisplayName(expression: null);
}
/// <summary>

View File

@ -8,100 +8,101 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
public static class EditorExtensions
{
public static HtmlString Editor(this IHtmlHelper html, string expression)
public static HtmlString Editor([NotNull] this IHtmlHelper html, string expression)
{
return html.Editor(expression, templateName: null, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString Editor(this IHtmlHelper html, string expression, object additionalViewData)
public static HtmlString Editor([NotNull] this IHtmlHelper html, string expression, object additionalViewData)
{
return html.Editor(expression, templateName: null, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString Editor(this IHtmlHelper html, string expression, string templateName)
public static HtmlString Editor([NotNull] this IHtmlHelper html, string expression, string templateName)
{
return html.Editor(expression, templateName, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString Editor(this IHtmlHelper html, string expression, string templateName,
public static HtmlString Editor([NotNull] this IHtmlHelper html, string expression, string templateName,
object additionalViewData)
{
return html.Editor(expression, templateName, htmlFieldName: null, additionalViewData: additionalViewData);
}
public static HtmlString Editor(this IHtmlHelper html, string expression, string templateName,
public static HtmlString Editor([NotNull] this IHtmlHelper html, string expression, string templateName,
string htmlFieldName)
{
return html.Editor(expression, templateName, htmlFieldName, additionalViewData: null);
}
public static HtmlString EditorFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression)
public static HtmlString EditorFor<TModel, TValue>([NotNull] this IHtmlHelper<TModel> html,
[NotNull] Expression<Func<TModel, TValue>> expression)
{
return html.EditorFor(expression, templateName: null, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString EditorFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, object additionalViewData)
public static HtmlString EditorFor<TModel, TValue>([NotNull] this IHtmlHelper<TModel> html,
[NotNull] Expression<Func<TModel, TValue>> expression, object additionalViewData)
{
return html.EditorFor(expression, templateName: null, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString EditorFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, string templateName)
public static HtmlString EditorFor<TModel, TValue>([NotNull] this IHtmlHelper<TModel> html,
[NotNull] Expression<Func<TModel, TValue>> expression, string templateName)
{
return html.EditorFor(expression, templateName, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString EditorFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, string templateName, object additionalViewData)
public static HtmlString EditorFor<TModel, TValue>([NotNull] this IHtmlHelper<TModel> html,
[NotNull] Expression<Func<TModel, TValue>> expression, string templateName, object additionalViewData)
{
return html.EditorFor(expression, templateName, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString EditorFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, string templateName, string htmlFieldName)
public static HtmlString EditorFor<TModel, TValue>([NotNull] this IHtmlHelper<TModel> html,
[NotNull] Expression<Func<TModel, TValue>> expression, string templateName, string htmlFieldName)
{
return html.EditorFor(expression, templateName, htmlFieldName, additionalViewData: null);
}
public static HtmlString EditorForModel(this IHtmlHelper html)
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html)
{
return html.Editor(expression: string.Empty, templateName: null, htmlFieldName: null,
additionalViewData: null);
return html.Editor(expression: null, templateName: null, htmlFieldName: null, additionalViewData: null);
}
public static HtmlString EditorForModel(this IHtmlHelper html, object additionalViewData)
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html, object additionalViewData)
{
return html.Editor(expression: string.Empty, templateName: null, htmlFieldName: null,
return html.Editor(expression: null, templateName: null, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString EditorForModel(this IHtmlHelper html, string templateName)
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html, string templateName)
{
return html.Editor(expression: string.Empty, templateName: templateName, htmlFieldName: null,
return html.Editor(expression: null, templateName: templateName, htmlFieldName: null,
additionalViewData: null);
}
public static HtmlString EditorForModel(this IHtmlHelper html, string templateName, object additionalViewData)
{
return html.Editor(expression: string.Empty, templateName: templateName, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString EditorForModel(this IHtmlHelper html, string templateName, string htmlFieldName)
{
return html.Editor(expression: string.Empty, templateName: templateName, htmlFieldName: htmlFieldName,
additionalViewData: null);
}
public static HtmlString EditorForModel(this IHtmlHelper html, string templateName, string htmlFieldName,
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html, string templateName,
object additionalViewData)
{
return html.Editor(expression: string.Empty, templateName: templateName, htmlFieldName: htmlFieldName,
return html.Editor(expression: null, templateName: templateName, htmlFieldName: null,
additionalViewData: additionalViewData);
}
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html, string templateName,
string htmlFieldName)
{
return html.Editor(expression: null, templateName: templateName, htmlFieldName: htmlFieldName,
additionalViewData: null);
}
public static HtmlString EditorForModel([NotNull] this IHtmlHelper html, string templateName,
string htmlFieldName, object additionalViewData)
{
return html.Editor(expression: null, templateName: templateName, htmlFieldName: htmlFieldName,
additionalViewData: additionalViewData);
}
}

View File

@ -47,12 +47,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
public static HtmlString LabelForModel([NotNull] this IHtmlHelper html, string labelText)
{
return html.Label(expression: string.Empty, labelText: labelText, htmlAttributes: null);
return html.Label(expression: null, labelText: labelText, htmlAttributes: null);
}
public static HtmlString LabelForModel([NotNull] this IHtmlHelper html, object htmlAttributes)
{
return html.Label(expression: string.Empty, labelText: null, htmlAttributes: htmlAttributes);
return html.Label(expression: null, labelText: null, htmlAttributes: htmlAttributes);
}
public static HtmlString LabelForModel(
@ -60,7 +60,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
string labelText,
object htmlAttributes)
{
return html.Label(expression: string.Empty, labelText: labelText, htmlAttributes: htmlAttributes);
return html.Label(expression: null, labelText: labelText, htmlAttributes: htmlAttributes);
}
}
}

View File

@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <returns>A <see cref="System.String"/> containing the element name.</returns>
public static string NameForModel([NotNull] this IHtmlHelper htmlHelper)
{
return htmlHelper.Name(string.Empty);
return htmlHelper.Name(name: null);
}
/// <summary>
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// <returns>A <see cref="System.String"/> containing the element Id.</returns>
public static string IdForModel([NotNull] this IHtmlHelper htmlHelper)
{
return htmlHelper.Id(string.Empty);
return htmlHelper.Id(name: null);
}
}
}

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </remarks>
public static string ValueForModel([NotNull] this IHtmlHelper htmlHelper)
{
return htmlHelper.Value(name: string.Empty, format: null);
return htmlHelper.Value(name: null, format: null);
}
/// <summary>
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </remarks>
public static string ValueForModel([NotNull] this IHtmlHelper htmlHelper, string format)
{
return htmlHelper.Value(name: string.Empty, format: format);
return htmlHelper.Value(name: null, format: format);
}
}
}

View File

@ -236,7 +236,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// </summary>
/// <param name="name">The name of the HTML element.</param>
/// <returns>The ID of the HTML element.</returns>
string GenerateIdFromName(string name);
string GenerateIdFromName([NotNull] string name);
/// <summary>
/// Returns information about about client validation rules for the given <paramref name="metadata"/> or
@ -491,6 +491,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// Converts the expression result to a <see cref="System.String"/> directly if
/// <paramref name="format"/> is <c>null</c> or empty.
/// </remarks>
string Value([NotNull] string name, string format);
string Value(string name, string format);
}
}

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.Core
DefaultTemplatesUtilities.GetHtmlHelper<IEnumerable<DefaultTemplatesUtilities.ObjectTemplateModel>>(null);
// Act
var displayNameResult = helper.DisplayName("");
var displayNameResult = helper.DisplayName(expression: string.Empty);
var displayNameNullResult = helper.DisplayName(expression: null); // null is another alias for current model
var displayNameForResult = helper.DisplayNameFor(m => m);
var displayNameForEnumerableModelResult = enumerableHelper.DisplayNameFor(m => m);
@ -96,7 +96,7 @@ namespace Microsoft.AspNet.Mvc.Core
enumerableHelper.ViewData.ModelMetadata = metadata;
// Act
var displayNameResult = helper.DisplayName("");
var displayNameResult = helper.DisplayName(expression: string.Empty);
var displayNameForResult = helper.DisplayNameFor(m => m);
var displayNameForEnumerableResult = enumerableHelper.DisplayNameFor(m => m);
var displayNameForModelResult = helper.DisplayNameForModel();
@ -153,7 +153,7 @@ namespace Microsoft.AspNet.Mvc.Core
enumerableHelper.ViewData.ModelMetadata.DisplayName = displayName;
// Act
var displayNameResult = helper.DisplayName("");
var displayNameResult = helper.DisplayName(expression: string.Empty);
var displayNameForResult = helper.DisplayNameFor(m => m);
var displayNameForEnumerableResult = enumerableHelper.DisplayNameFor(m => m);
var displayNameForModelResult = helper.DisplayNameForModel();

View File

@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper<OverriddenToStringModel>(model: null);
// Act
var result = helper.DisplayText("");
var result = helper.DisplayText(name: string.Empty);
// Assert
Assert.Empty(result);
@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata.NullDisplayText = "Null display Text";
// Act
var result = helper.DisplayText("");
var result = helper.DisplayText(name: string.Empty);
// Assert
Assert.Equal("Null display Text", result);
@ -75,10 +75,12 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
// Act
var result = helper.DisplayText("");
var result = helper.DisplayText(name: string.Empty);
var nullResult = helper.DisplayText(name: null); // null is another alias for current model
// Assert
Assert.Equal("Model value", result);
Assert.Equal("Model value", nullResult);
}
[Fact]
@ -118,7 +120,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata.SimpleDisplayText = "Simple display text";
// Act
var result = helper.DisplayText("");
var result = helper.DisplayText(name: string.Empty);
// Assert
Assert.Equal("Simple display text", result);

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata = metadata;
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata = metadata;
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
@ -152,7 +152,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata.DisplayName = string.Empty;
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
@ -174,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.ModelMetadata.DisplayName = displayName;
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
@ -195,7 +195,7 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper(metadataHelper.MetadataProvider.Object);
// Act
var labelResult = helper.Label("");
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();

View File

@ -25,11 +25,11 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var idResult = helper.Id("");
var idResult = helper.Id(name: string.Empty);
var idNullResult = helper.Id(name: null); // null is another alias for current model
var idForResult = helper.IdFor(m => m);
var idForModelResult = helper.IdForModel();
var nameResult = helper.Name("");
var nameResult = helper.Name(name: string.Empty);
var nameNullResult = helper.Name(name: null);
var nameForResult = helper.NameFor(m => m);
var nameForModelResult = helper.NameForModel();
@ -58,10 +58,10 @@ namespace Microsoft.AspNet.Mvc.Core
helper.ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
// Act
var idResult = helper.Id("");
var idResult = helper.Id(name: string.Empty);
var idForResult = helper.IdFor(m => m);
var idForModelResult = helper.IdForModel();
var nameResult = helper.Name("");
var nameResult = helper.Name(name: string.Empty);
var nameForResult = helper.NameFor(m => m);
var nameForModelResult = helper.NameForModel();
@ -152,10 +152,10 @@ namespace Microsoft.AspNet.Mvc.Core
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider.Object);
// Act (do not throw)
var idResult = helper.Id("");
var idResult = helper.Id(name: string.Empty);
var idForResult = helper.IdFor(m => m);
var idForModelResult = helper.IdForModel();
var nameResult = helper.Name("");
var nameResult = helper.Name(name: string.Empty);
var nameForResult = helper.NameFor(m => m);
var nameForModelResult = helper.NameForModel();

View File

@ -94,6 +94,7 @@ namespace Microsoft.AspNet.Mvc.Core
// Act & Assert
Assert.Equal(expectedModelValue, helper.Value(name: string.Empty));
Assert.Equal(expectedModelValue, helper.Value(name: null)); // null is another alias for current model
Assert.Equal(expectedModelValue, helper.ValueFor(m => m));
Assert.Equal(expectedModelValue, helper.ValueForModel());
}