Change `ValidationSummaryTagHelper`'s property to `ValidationSummary` enum
- #1685 - move `ValidationSummary` type to the `Microsoft.AspNet.Mvc` namespace - update tests and samples to match - remove tests for case-insensitivity of `ValidationSummary` property values
This commit is contained in:
parent
60fa4a6f45
commit
9b2a9e3976
|
|
@ -14,13 +14,14 @@
|
|||
<div class="form-horizontal">
|
||||
@* validation summary tag helper will target just <div/> elements and append the list of errors *@
|
||||
@* - i.e. this helper, like <select/> helper, has ContentBehavior.Append *@
|
||||
@* helper does nothing if model is valid and (client-side validation is disabled or asp-validation-summary="ModelOnly") *@
|
||||
@* helper does nothing if model is valid and (client-side validation is disabled or
|
||||
asp-validation-summary="ValidationSummary.ModelOnly") *@
|
||||
@* don't need a bound attribute to match Html.ValidationSummary()'s headerTag parameter; users wrap message as they wish *@
|
||||
@* initially at least, will not remove the <div/> if list isn't generated *@
|
||||
@* - should helper remove the <div/> if list isn't generated? *@
|
||||
@* - (Html.ValidationSummary returns empty string despite non-empty message parameter) *@
|
||||
@* Acceptable values are: "None", "ModelOnly" and "All" *@
|
||||
<div asp-validation-summary="All" style="color:blue" id="validation_day" class="form-group">
|
||||
<div asp-validation-summary="ValidationSummary.All" style="color:blue" id="validation_day" class="form-group">
|
||||
<span style="color:red">This is my message</span>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<form>
|
||||
<div class="form-horizontal">
|
||||
<div asp-validation-summary="All" />
|
||||
<div asp-validation-summary="ValidationSummary.All" />
|
||||
<input type="hidden" asp-for="Id" />
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -154,6 +154,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_NoProvidedMetadata"), p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.
|
||||
/// </summary>
|
||||
internal static string InvalidEnumArgument
|
||||
{
|
||||
get { return GetString("InvalidEnumArgument"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidEnumArgument(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidEnumArgument"), p0, p1, p2);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -144,4 +144,7 @@
|
|||
<data name="TagHelpers_NoProvidedMetadata" xml:space="preserve">
|
||||
<value>The {2} was unable to provide metadata about '{1}' expression value '{3}' for {0}.</value>
|
||||
</data>
|
||||
<data name="InvalidEnumArgument" xml:space="preserve">
|
||||
<value>The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Acceptable validation summary rendering modes.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
public class ValidationSummaryTagHelper : TagHelper
|
||||
{
|
||||
private const string ValidationSummaryAttributeName = "asp-validation-summary";
|
||||
private ValidationSummary _validationSummary;
|
||||
|
||||
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
|
||||
[Activate]
|
||||
|
|
@ -27,51 +28,60 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
protected internal IHtmlGenerator Generator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <c>All</c> or <c>ModelOnly</c>, appends a validation summary. Acceptable values are defined by the
|
||||
/// <see cref="ValidationSummary"/> enum.
|
||||
/// If <see cref="ValidationSummary.All"/> or <see cref="ValidationSummary.ModelOnly"/>, appends a validation
|
||||
/// summary. Otherwise (<see cref="ValidationSummary.None"/>, the default), this tag helper does nothing.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown if setter is called with an undefined <see cref="ValidationSummary"/> value e.g.
|
||||
/// <c>(ValidationSummary)23</c>.
|
||||
/// </exception>
|
||||
[HtmlAttributeName(ValidationSummaryAttributeName)]
|
||||
public string ValidationSummaryValue { get; set; }
|
||||
public ValidationSummary ValidationSummary
|
||||
{
|
||||
get
|
||||
{
|
||||
return _validationSummary;
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case ValidationSummary.All:
|
||||
case ValidationSummary.ModelOnly:
|
||||
case ValidationSummary.None:
|
||||
_validationSummary = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException(
|
||||
message: Resources.FormatInvalidEnumArgument(
|
||||
nameof(value),
|
||||
value,
|
||||
typeof(ValidationSummary).FullName),
|
||||
paramName: nameof(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>Does nothing if <see cref="ValidationSummaryValue"/> is <c>null</c>, empty or "None".</remarks>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if <see cref="ValidationSummaryValue"/> is not a valid <see cref="ValidationSummary"/> value.
|
||||
/// </exception>
|
||||
/// <remarks>Does nothing if <see cref="ValidationSummary"/> is <see cref="ValidationSummary.None"/>.</remarks>
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ValidationSummaryValue))
|
||||
if (ValidationSummary == ValidationSummary.None)
|
||||
{
|
||||
ValidationSummary validationSummaryValue;
|
||||
if (!Enum.TryParse(ValidationSummaryValue, ignoreCase: true, result: out validationSummaryValue))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
Resources.FormatTagHelpers_InvalidValue_ThreeAcceptableValues(
|
||||
"<div>",
|
||||
ValidationSummaryAttributeName,
|
||||
ValidationSummaryValue,
|
||||
ValidationSummary.All,
|
||||
ValidationSummary.ModelOnly,
|
||||
ValidationSummary.None));
|
||||
}
|
||||
else if (validationSummaryValue == ValidationSummary.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var validationModelErrorsOnly = validationSummaryValue == ValidationSummary.ModelOnly;
|
||||
var tagBuilder = Generator.GenerateValidationSummary(
|
||||
ViewContext,
|
||||
excludePropertyErrors: validationModelErrorsOnly,
|
||||
message: null,
|
||||
headerTag: null,
|
||||
htmlAttributes: null);
|
||||
|
||||
if (tagBuilder != null)
|
||||
{
|
||||
output.MergeAttributes(tagBuilder);
|
||||
output.Content += tagBuilder.InnerHtml;
|
||||
}
|
||||
var tagBuilder = Generator.GenerateValidationSummary(
|
||||
ViewContext,
|
||||
excludePropertyErrors: ValidationSummary == ValidationSummary.ModelOnly,
|
||||
message: null,
|
||||
headerTag: null,
|
||||
htmlAttributes: null);
|
||||
if (tagBuilder != null)
|
||||
{
|
||||
output.MergeAttributes(tagBuilder);
|
||||
output.Content += tagBuilder.InnerHtml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
|||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -17,6 +18,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
{
|
||||
public class ValidationSummaryTagHelperTest
|
||||
{
|
||||
public void Concstructor_IntializesProperties_AsExpected()
|
||||
{
|
||||
// Arrange & Act
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper();
|
||||
|
||||
// Assert
|
||||
Assert.Null(validationSummaryTagHelper.Generator);
|
||||
Assert.Null(validationSummaryTagHelper.ViewContext);
|
||||
Assert.Equal(ValidationSummary.None, validationSummaryTagHelper.ValidationSummary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_GeneratesExpectedOutput()
|
||||
{
|
||||
|
|
@ -25,7 +37,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = "All"
|
||||
ValidationSummary = ValidationSummary.All,
|
||||
};
|
||||
|
||||
var tagHelperContext = new TagHelperContext(new Dictionary<string, object>(), uniqueId: "test");
|
||||
|
|
@ -57,13 +69,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
Assert.Equal(expectedTagName, output.TagName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_CallsIntoGenerateValidationSummaryWithExpectedParameters()
|
||||
[Theory]
|
||||
[InlineData(ValidationSummary.All, false)]
|
||||
[InlineData(ValidationSummary.ModelOnly, true)]
|
||||
public async Task ProcessAsync_CallsIntoGenerateValidationSummaryWithExpectedParameters(
|
||||
ValidationSummary validationSummary,
|
||||
bool expectedExcludePropertyErrors)
|
||||
{
|
||||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = "ModelOnly",
|
||||
ValidationSummary = validationSummary,
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
|
|
@ -72,7 +88,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
var expectedViewContext = CreateViewContext();
|
||||
var generator = new Mock<IHtmlGenerator>();
|
||||
generator
|
||||
.Setup(mock => mock.GenerateValidationSummary(expectedViewContext, true, null, null, null))
|
||||
.Setup(mock => mock.GenerateValidationSummary(
|
||||
expectedViewContext,
|
||||
expectedExcludePropertyErrors,
|
||||
null, // message
|
||||
null, // headerTag
|
||||
null)) // htmlAttributes
|
||||
.Returns(new TagBuilder("div"))
|
||||
.Verifiable();
|
||||
validationSummaryTagHelper.ViewContext = expectedViewContext;
|
||||
|
|
@ -93,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = "ModelOnly"
|
||||
ValidationSummary = ValidationSummary.ModelOnly,
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
|
|
@ -136,15 +157,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
Assert.Equal("Content of validation summaryNew HTML", output.Content);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
public async Task ProcessAsync_DoesNothingIfNullOrEmptyValidationSummaryValue(string validationSummaryValue)
|
||||
[Fact]
|
||||
public async Task ProcessAsync_DoesNothingIfValidationSummaryNone()
|
||||
{
|
||||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = validationSummaryValue
|
||||
ValidationSummary = ValidationSummary.None,
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
|
|
@ -166,16 +185,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("All")]
|
||||
[InlineData("all")]
|
||||
[InlineData("ModelOnly")]
|
||||
[InlineData("modelonly")]
|
||||
public async Task ProcessAsync_GeneratesValidationSummaryWhenNotNone_IgnoresCase(string validationSummary)
|
||||
[InlineData(ValidationSummary.All)]
|
||||
[InlineData(ValidationSummary.ModelOnly)]
|
||||
public async Task ProcessAsync_GeneratesValidationSummaryWhenNotNone(ValidationSummary validationSummary)
|
||||
{
|
||||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = validationSummary
|
||||
ValidationSummary = validationSummary,
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
|
|
@ -211,56 +228,24 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("None")]
|
||||
[InlineData("none")]
|
||||
public async Task ProcessAsync_DoesNotGenerateValidationSummaryWhenNone_IgnoresCase(string validationSummary)
|
||||
[InlineData((ValidationSummary)(-1))]
|
||||
[InlineData((ValidationSummary)23)]
|
||||
[InlineData(ValidationSummary.All | ValidationSummary.ModelOnly)]
|
||||
[ReplaceCulture]
|
||||
public void ValidationSummaryProperty_ThrowsWhenSetToInvalidValidationSummaryValue(
|
||||
ValidationSummary validationSummary)
|
||||
{
|
||||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = validationSummary
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
attributes: new Dictionary<string, string>(),
|
||||
content: "Content of validation message");
|
||||
var tagBuilder = new TagBuilder("span2")
|
||||
{
|
||||
InnerHtml = "New HTML"
|
||||
};
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper();
|
||||
var expectedMessage = string.Format(
|
||||
@"The value of argument 'value' ({0}) is invalid for Enum type 'Microsoft.AspNet.Mvc.ValidationSummary'.
|
||||
Parameter name: value",
|
||||
validationSummary);
|
||||
|
||||
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||
|
||||
// Act
|
||||
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("div", output.TagName);
|
||||
Assert.Empty(output.Attributes);
|
||||
Assert.Equal("Content of validation message", output.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessAsync_ThrowsWhenInvalidValidationSummaryValue()
|
||||
{
|
||||
// Arrange
|
||||
var validationSummaryTagHelper = new ValidationSummaryTagHelper
|
||||
{
|
||||
ValidationSummaryValue = "Hello World"
|
||||
};
|
||||
var output = new TagHelperOutput(
|
||||
"div",
|
||||
attributes: new Dictionary<string, string>(),
|
||||
content: "Content of validation message");
|
||||
var expectedViewContext = CreateViewContext();
|
||||
var expectedMessage = "Cannot parse 'asp-validation-summary' value 'Hello World' for <div>. Acceptable " +
|
||||
"values are 'All', 'ModelOnly' and 'None'.";
|
||||
|
||||
// Act
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => validationSummaryTagHelper.ProcessAsync(context: null, output: output));
|
||||
|
||||
// Assert
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<ArgumentException>(
|
||||
"value",
|
||||
() => { validationSummaryTagHelper.ValidationSummary = validationSummary; });
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<select asp-for="Product" asp-items="(IEnumerable<SelectListItem>)ViewBag.Items" />
|
||||
<span asp-validation-for="Product" />
|
||||
</div>
|
||||
<div asp-validation-summary="All" class="warehouse" />
|
||||
<div asp-validation-summary="ValidationSummary.All" class="warehouse" />
|
||||
<input type="submit" />
|
||||
}
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
@Html.EditorFor(model => model.Customer.Gender)
|
||||
<span asp-validation-for="Customer.Gender" />
|
||||
</div>
|
||||
<div asp-validation-summary="All" class="order" />
|
||||
<div asp-validation-summary="ValidationSummary.All" class="order" />
|
||||
<input type="hidden" asp-for="Customer.Key" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@
|
|||
<input asp-for="Gender" type="radio" value="Female" /> Female
|
||||
<span asp-validation-for="Gender" />
|
||||
</div>
|
||||
<div asp-validation-summary="All" class="order" />
|
||||
<div asp-validation-summary="ModelOnly" class="order" />
|
||||
<div asp-validation-summary="ValidationSummary.All" class="order" />
|
||||
<div asp-validation-summary="ValidationSummary.ModelOnly" class="order" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
<div class="form-horizontal">
|
||||
<h4>Employee</h4>
|
||||
<hr />
|
||||
<div asp-validation-summary="All" class="text-danger">
|
||||
<div asp-validation-summary="ValidationSummary.All" class="text-danger">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Age" class="control-label col-md-2" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue