diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/InputObjectBindingTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/InputObjectBindingTests.cs index c7863edad1..2cfd3b4524 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/InputObjectBindingTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/InputObjectBindingTests.cs @@ -15,7 +15,7 @@ using Microsoft.Framework.OptionsModel; using Moq; using Xunit; -namespace Microsoft.AspNet.Mvc.Core.Test +namespace Microsoft.AspNet.Mvc { public class InputObjectBindingTests { @@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test Assert.False(modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.ErrorCount); Assert.Equal( - "The field UserName must be a string or array type with a minimum length of '5'.", + ValidationAttributeUtil.GetMinLengthErrorMessage(5, "UserName"), Assert.Single(Assert.Single(modelStateDictionary.Values).Errors).ErrorMessage); var model = result["foo"] as User; Assert.Equal(sampleName, model.Name); @@ -113,10 +113,10 @@ namespace Microsoft.AspNet.Mvc.Core.Test Assert.Equal(2, modelStateDictionary.ErrorCount); var model = result["foo"] as Customers; Assert.Equal( - "The field UserName must be a string or array type with a minimum length of '5'.", + ValidationAttributeUtil.GetMinLengthErrorMessage(5, "UserName"), modelStateDictionary["foo.Users[0].UserName"].Errors[0].ErrorMessage); Assert.Equal( - "The field UserName must be a string or array type with a minimum length of '5'.", + ValidationAttributeUtil.GetMinLengthErrorMessage(5, "UserName"), modelStateDictionary["foo.Users[1].UserName"].Errors[0].ErrorMessage); Assert.Equal(2, model.Users.Count); Assert.Equal(sampleFirstUser, model.Users[0].Name); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Utils/ValidationAttributeUtil.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Utils/ValidationAttributeUtil.cs new file mode 100644 index 0000000000..2dfd87d2b3 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Utils/ValidationAttributeUtil.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.ComponentModel.DataAnnotations; + +namespace Microsoft.AspNet.Mvc +{ + public static class ValidationAttributeUtil + { + public static string GetMinLengthErrorMessage(int length, string field) + { + var attr = new MinLengthAttribute(length); + return attr.FormatErrorMessage(field); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Utils/ValidationAttributeUtil.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Utils/ValidationAttributeUtil.cs index 6db239e0ee..e9b51bceb2 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Utils/ValidationAttributeUtil.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Utils/ValidationAttributeUtil.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.ComponentModel.DataAnnotations; namespace Microsoft.AspNet.Mvc.ModelBinding @@ -13,5 +12,34 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var attr = new RequiredAttribute(); return attr.FormatErrorMessage(field); } + + public static string GetStringLengthErrorMessage(int? minimumLength, int maximumLength, string field) + { + var attr = new StringLengthAttribute(maximumLength); + if (minimumLength != null) + { + attr.MinimumLength = (int)minimumLength; + } + + return attr.FormatErrorMessage(field); + } + + public static string GetMaxLengthErrorMessage(int maximumLength, string field) + { + var attr = new MaxLengthAttribute(maximumLength); + return attr.FormatErrorMessage(field); + } + + public static string GetRegExErrorMessage(string pattern, string field) + { + var attr = new RegularExpressionAttribute(pattern); + return attr.FormatErrorMessage(field); + } + + public static string GetRangeErrorMessage(int min, int max, string field) + { + var attr = new RangeAttribute(min, max); + return attr.FormatErrorMessage(field); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Validation/DefaultBodyModelValidatorTests.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Validation/DefaultBodyModelValidatorTests.cs index 5e09f4b7e9..6ab7c721ae 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Validation/DefaultBodyModelValidatorTests.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Validation/DefaultBodyModelValidatorTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Linq; using Microsoft.AspNet.Mvc.OptionDescriptors; using Microsoft.AspNet.Testing; using Microsoft.Framework.DependencyInjection; @@ -35,111 +36,173 @@ namespace Microsoft.AspNet.Mvc.ModelBinding yield return new object[] { "foo", typeof(string), new Dictionary() }; // Object Traversal : make sure we can traverse the object graph without throwing - yield return new object[] { new ValueType() { Reference = "ref", Value = 256 }, typeof(ValueType), new Dictionary() }; - yield return new object[] { new ReferenceType() { Reference = "ref", Value = 256 }, typeof(ReferenceType), new Dictionary() }; + yield return new object[] + { + new ValueType() { Reference = "ref", Value = 256 }, + typeof(ValueType), + new Dictionary() + }; + yield return new object[] + { + new ReferenceType() { Reference = "ref", Value = 256 }, + typeof(ReferenceType), + new Dictionary() + }; // Classes - yield return new object[] { new Person() { Name = "Rick", Profession = "Astronaut" }, typeof(Person), new Dictionary() }; - yield return new object[] { new Person(), typeof(Person), new Dictionary() - { - { "Name", "The Name field is required." }, - { "Profession", "The Profession field is required." } - } - }; + yield return new object[] + { + new Person() { Name = "Rick", Profession = "Astronaut" }, + typeof(Person), + new Dictionary() + }; + yield return new object[] + { + new Person(), + typeof(Person), + new Dictionary() + { + { "Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } + } + }; - yield return new object[] { new Person() { Name = "Rick", Friend = new Person() }, typeof(Person), new Dictionary() - { - { "Profession", "The Profession field is required." }, - { "Friend.Name", "The Name field is required." }, - { "Friend.Profession", "The Profession field is required." } - } - }; + yield return new object[] + { + new Person() { Name = "Rick", Friend = new Person() }, + typeof(Person), + new Dictionary() + { + { "Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") }, + { "Friend.Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "Friend.Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } + } + }; // Collections - yield return new object[] { new Person[] { new Person(), new Person() }, typeof(Person[]), new Dictionary() - { - { "[0].Name", "The Name field is required." }, - { "[0].Profession", "The Profession field is required." }, - { "[1].Name", "The Name field is required." }, - { "[1].Profession", "The Profession field is required." } - } - }; + yield return new object[] + { + new Person[] { new Person(), new Person() }, + typeof(Person[]), + new Dictionary() + { + { "[0].Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[0].Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") }, + { "[1].Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[1].Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } + } + }; - yield return new object[] { new List { new Person(), new Person() }, typeof(Person[]), new Dictionary() - { - { "[0].Name", "The Name field is required." }, - { "[0].Profession", "The Profession field is required." }, - { "[1].Name", "The Name field is required." }, - { "[1].Profession", "The Profession field is required." } - } - }; + yield return new object[] + { + new List { new Person(), new Person() }, + typeof(Person[]), + new Dictionary() + { + { "[0].Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[0].Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") }, + { "[1].Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[1].Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } + } + }; - yield return new object[] { new Dictionary { { "Joe", new Person() } , { "Mark", new Person() } }, typeof(Dictionary), new Dictionary() + if (!TestPlatformHelper.IsMono) + { + // In Mono this throws a NullRef Exception. + // Should be investigated - https://github.com/aspnet/Mvc/issues/1261 + yield return new object[] + { + new Dictionary { { "Joe", new Person() } , { "Mark", new Person() } }, + typeof(Dictionary), + new Dictionary() { - { "[0].Value.Name", "The Name field is required." }, - { "[0].Value.Profession", "The Profession field is required." }, - { "[1].Value.Name", "The Name field is required." }, - { "[1].Value.Profession", "The Profession field is required." } + { "[0].Value.Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[0].Value.Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") }, + { "[1].Value.Name", ValidationAttributeUtil.GetRequiredErrorMessage("Name") }, + { "[1].Value.Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } } }; + } // IValidatableObject's - yield return new object[] { new ValidatableModel(), typeof(ValidatableModel), new Dictionary() - { - { "", "Error1" }, - { "Property1", "Error2" }, - { "Property2", "Error3" }, - { "Property3", "Error3" } - } - }; + yield return new object[] + { + new ValidatableModel(), + typeof(ValidatableModel), + new Dictionary() + { + { "", "Error1" }, + { "Property1", "Error2" }, + { "Property2", "Error3" }, + { "Property3", "Error3" } + } + }; - yield return new object[]{ new[] { new ValidatableModel() }, typeof(ValidatableModel[]), new Dictionary() - { - { "[0]", "Error1" }, - { "[0].Property1", "Error2" }, - { "[0].Property2", "Error3" }, - { "[0].Property3", "Error3" } - } - }; + yield return new object[] + { + new[] { new ValidatableModel() }, + typeof(ValidatableModel[]), + new Dictionary() + { + { "[0]", "Error1" }, + { "[0].Property1", "Error2" }, + { "[0].Property2", "Error3" }, + { "[0].Property3", "Error3" } + } + }; // Nested Objects - yield return new object[] { new Org() { - Id = 1, - OrgName = "Org", - Dev = new Team - { - Id = 10, - TeamName = "HelloWorldTeam", - Lead = "SampleLeadDev", - TeamSize = 2 - }, - Test = new Team - { - Id = 11, - TeamName = "HWT", - Lead = "SampleTestLead", - TeamSize = 12 - } - }, typeof(Org), new Dictionary() - { - { "OrgName", "The field OrgName must be a string with a minimum length of 4 and a maximum length of 20." }, - { "Dev.Lead", "The field Lead must be a string or array type with a maximum length of '10'." }, - { "Dev.TeamSize", "The field TeamSize must be between 3 and 100." }, - { "Test.TeamName", "The field TeamName must be a string with a minimum length of 4 and a maximum length of 20." }, - { "Test.Lead", "The field Lead must be a string or array type with a maximum length of '10'." } - } + yield return new object[] + { + new Org() + { + Id = 1, + OrgName = "Org", + Dev = new Team + { + Id = 10, + TeamName = "HelloWorldTeam", + Lead = "SampleLeadDev", + TeamSize = 2 + }, + Test = new Team + { + Id = 11, + TeamName = "HWT", + Lead = "SampleTestLead", + TeamSize = 12 + } + }, + typeof(Org), + new Dictionary() + { + { "OrgName", ValidationAttributeUtil.GetStringLengthErrorMessage(4, 20, "OrgName") }, + { "Dev.Lead", ValidationAttributeUtil.GetMaxLengthErrorMessage(10, "Lead") }, + { "Dev.TeamSize", ValidationAttributeUtil.GetRangeErrorMessage(3, 100, "TeamSize") }, + { "Test.TeamName", ValidationAttributeUtil.GetStringLengthErrorMessage(4, 20, "TeamName") }, + { "Test.Lead", ValidationAttributeUtil.GetMaxLengthErrorMessage(10, "Lead") } + } }; // Testing we don't validate fields - yield return new object[] { new VariableTest() { test = 5 }, typeof(VariableTest), new Dictionary() }; + yield return new object[] + { + new VariableTest() { test = 5 }, + typeof(VariableTest), + new Dictionary() + }; // Testing we don't blow up on cycles - yield return new object[] { LonelyPerson, typeof(Person), new Dictionary() - { - { "Name", "The field Name must be a string with a maximum length of 10." }, - { "Profession", "The Profession field is required." } - } - }; + yield return new object[] + { + LonelyPerson, + typeof(Person), + new Dictionary() + { + { "Name", ValidationAttributeUtil.GetStringLengthErrorMessage(null, 10, "Name") }, + { "Profession", ValidationAttributeUtil.GetRequiredErrorMessage("Profession") } + } + }; } } @@ -209,12 +272,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding Assert.Contains("Street", validationContext.ModelState.Keys); var streetState = validationContext.ModelState["Street"]; Assert.Equal(2, streetState.Errors.Count); - Assert.Equal( - "The field Street must be a string with a maximum length of 5.", - streetState.Errors[0].ErrorMessage); - Assert.Equal( - "The field Street must match the regular expression 'hehehe'.", - streetState.Errors[1].ErrorMessage); + var errorCollection = streetState.Errors.Select(e => e.ErrorMessage); + Assert.Contains(ValidationAttributeUtil.GetStringLengthErrorMessage(null, 5, "Street"), errorCollection); + Assert.Contains(ValidationAttributeUtil.GetRegExErrorMessage("hehehe", "Street"), errorCollection); } [Fact]