diff --git a/CaPPMS/Attributes/CappmsStringLengthAttribute.cs b/CaPPMS/Attributes/CappmsStringLengthAttribute.cs new file mode 100644 index 0000000..196ae3a --- /dev/null +++ b/CaPPMS/Attributes/CappmsStringLengthAttribute.cs @@ -0,0 +1,52 @@ +using System.ComponentModel.DataAnnotations; + +namespace CaPPMS.Attributes +{ + /// + /// Provides a custom string length attribute that includes the current length of the string in the error message. + /// + public class CappmsStringLengthAttribute : StringLengthAttribute + { + private string? context; + + /// + /// Initializes a new instance of the class. + /// + /// The maximum length of the object shall be. + public CappmsStringLengthAttribute(int maximumLength) : base(maximumLength) + { + } + + /// + /// Override the default IsValid method to store the current string value. + /// + /// The object to validate. + /// true if valid. + public override bool IsValid(object? value) + { + if (value is string str) + { + this.context = str; + } + + return base.IsValid(value); + } + + /// + /// Override the default error message to include the current length of the string. + /// + /// Property Name. + /// A formatted message. + public override string FormatErrorMessage(string name) + { + if (this.context != null) + { + string message = base.FormatErrorMessage(name); + message += $" Current length:{this.context.Length}."; + return message; + } + + return base.FormatErrorMessage(name); + } + } +} diff --git a/CaPPMS/CaPPMS.sln b/CaPPMS/CaPPMS.sln index c50d584..f9d79b0 100644 --- a/CaPPMS/CaPPMS.sln +++ b/CaPPMS/CaPPMS.sln @@ -1,6 +1,12 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35913.81 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CaPPMS", "CaPPMS.csproj", "{AA9B970F-5351-4EA2-A78C-7E83F05C57C1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaPPMSTests", "..\CaPPMSTests\CaPPMSTests.csproj", "{5A356024-F9CF-BC44-22A7-4FEE4DBA2663}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -11,6 +17,10 @@ Global {AA9B970F-5351-4EA2-A78C-7E83F05C57C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA9B970F-5351-4EA2-A78C-7E83F05C57C1}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA9B970F-5351-4EA2-A78C-7E83F05C57C1}.Release|Any CPU.Build.0 = Release|Any CPU + {5A356024-F9CF-BC44-22A7-4FEE4DBA2663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A356024-F9CF-BC44-22A7-4FEE4DBA2663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A356024-F9CF-BC44-22A7-4FEE4DBA2663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A356024-F9CF-BC44-22A7-4FEE4DBA2663}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CaPPMS/Model/Review.cs b/CaPPMS/Model/Review.cs index 76e0adb..b4e9361 100644 --- a/CaPPMS/Model/Review.cs +++ b/CaPPMS/Model/Review.cs @@ -7,6 +7,11 @@ namespace CaPPMS.Model [SqlTableName("StudentReviews")] public class Review : ISqlTableModel { + /// + /// The maximum length of a string in the database. + /// + public const int MaxStringLength = 4 * 1024; + public Review() { } [SqlIdProperty] @@ -29,7 +34,10 @@ public Review() { } public string Score { get; set; } = "0"; [Required(ErrorMessage = "Your comments for the student are appreciated.", AllowEmptyStrings = false)] - [StringLength(maximumLength: 255, MinimumLength = 25, ErrorMessage = "Please use at least 25 characters to describe the interaction of this student.")] + [CappmsStringLength( + maximumLength: MaxStringLength, + MinimumLength = 25, + ErrorMessage = "Please use at least {2} characters to describe the interaction of this student and at most {1} characters.")] public string Comments { get; set; } = string.Empty; } } \ No newline at end of file diff --git a/CaPPMSTests/Attribute/CappmsStringLengthAttributeTests.cs b/CaPPMSTests/Attribute/CappmsStringLengthAttributeTests.cs new file mode 100644 index 0000000..b97ee49 --- /dev/null +++ b/CaPPMSTests/Attribute/CappmsStringLengthAttributeTests.cs @@ -0,0 +1,55 @@ +using CaPPMS.Attributes; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Threading.Tasks; + +namespace CaPPMSTests.Attribute +{ + [TestClass] + public class CappmsStringLengthAttributeTests + { + [TestMethod] + public async Task StringIsValid() + { + // Arrange + var attribute = new CappmsStringLengthAttribute(100) + { + MinimumLength = 5, + }; + + string value = "This is a test string."; + Assert.IsTrue(attribute.IsValid(value)); + await Task.CompletedTask; + } + + [TestMethod] + public async Task StringIsInvalidMinLen() + { + // Arrange + var attribute = new CappmsStringLengthAttribute(100) + { + MinimumLength = 5, + }; + string value = "Test"; + Assert.IsFalse(attribute.IsValid(value)); + string errorMessage = attribute.FormatErrorMessage("Test"); + Assert.AreEqual("The field Test must be a string with a minimum length of 5 and a maximum length of 100. Current length:4.", errorMessage); + + await Task.CompletedTask; + } + + [TestMethod] + public async Task StringIsInvalidMaxLen() + { + // Arrange + var attribute = new CappmsStringLengthAttribute(10) + { + MinimumLength = 5, + }; + string value = "This is a test string."; + Assert.IsFalse(attribute.IsValid(value)); + string errorMessage = attribute.FormatErrorMessage("Test"); + Assert.AreEqual("The field Test must be a string with a minimum length of 5 and a maximum length of 10. Current length:22.", errorMessage); + await Task.CompletedTask; + } + } +} diff --git a/CaPPMSTests/Model/Table/TableTests.cs b/CaPPMSTests/Model/Table/TableTests.cs index 2ed13fc..fe316e3 100644 --- a/CaPPMSTests/Model/Table/TableTests.cs +++ b/CaPPMSTests/Model/Table/TableTests.cs @@ -1,4 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using CaPPMS.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; namespace CaPPMSTests.Model.Table { @@ -8,7 +9,7 @@ public class TableTests [TestMethod] public void NumberOfColumns() { - var table = new CaPPMS.Model.Table.Table() + var table = new CaPPMS.Model.Table.Table() { DataSource = new IEnumberableDummyObject() }; @@ -19,7 +20,7 @@ public void NumberOfColumns() [TestMethod] public void ColumnNames() { - var table = new CaPPMS.Model.Table.Table() + var table = new CaPPMS.Model.Table.Table() { DataSource = new IEnumberableDummyObject() }; @@ -31,7 +32,7 @@ public void ColumnNames() [TestMethod] public void VerifySingleRow() { - var table = new CaPPMS.Model.Table.Table() + var table = new CaPPMS.Model.Table.Table() { DataSource = new IEnumberableDummyObject() };