Gets the c# side of things working for complex validation for complex editors

This commit is contained in:
Shannon
2020-06-24 10:20:25 +10:00
parent 80bbfaf7be
commit 29aaabcc6e
10 changed files with 102 additions and 80 deletions
@@ -97,17 +97,17 @@ namespace Umbraco.Tests.Web.Validation
[Test]
public void TestSerializer()
{
var nestedLevel2 = new NestedValidationResults();
var elementTypeResult2 = new ElementTypeValidationResult("type2");
var propertyTypeResult2 = new PropertyTypeValidationResult("prop2");
var nestedLevel2 = new ComplexEditorValidationResult();
var elementTypeResult2 = new ComplexEditorElementTypeValidationResult("type2");
var propertyTypeResult2 = new ComplexEditorPropertyTypeValidationResult("prop2");
propertyTypeResult2.ValidationResults.Add(new ValidationResult("error2-1", new[] { "level2" }));
propertyTypeResult2.ValidationResults.Add(new ValidationResult("error2-2", new[] { "level2" }));
elementTypeResult2.ValidationResults.Add(propertyTypeResult2);
nestedLevel2.ValidationResults.Add(elementTypeResult2);
var nestedLevel1 = new NestedValidationResults();
var elementTypeResult1 = new ElementTypeValidationResult("type1");
var propertyTypeResult1 = new PropertyTypeValidationResult("prop1");
var nestedLevel1 = new ComplexEditorValidationResult();
var elementTypeResult1 = new ComplexEditorElementTypeValidationResult("type1");
var propertyTypeResult1 = new ComplexEditorPropertyTypeValidationResult("prop1");
propertyTypeResult1.ValidationResults.Add(new ValidationResult("error1-1", new[] { "level1" }));
propertyTypeResult1.ValidationResults.Add(nestedLevel2); // This is a nested result within the level 1
elementTypeResult1.ValidationResults.Add(propertyTypeResult1);
@@ -115,6 +115,11 @@ namespace Umbraco.Tests.Web.Validation
var serialized = JsonConvert.SerializeObject(nestedLevel1, Formatting.Indented, new ValidationResultConverter());
Console.WriteLine(serialized);
var jsonNestedError = JsonConvert.DeserializeObject<JObject>(serialized);
Assert.AreEqual(JTokenType.Array, jsonNestedError["nestedValidation"].Type);
var nestedValidation = (JArray)jsonNestedError["nestedValidation"];
AssertNestedValidation(nestedValidation);
}
[Test]
@@ -226,12 +231,12 @@ namespace Umbraco.Tests.Web.Validation
var jsonNestedError = JsonConvert.DeserializeObject<JObject>(nestedError.ErrorMessage);
Assert.AreEqual(JTokenType.Array, jsonNestedError["nestedValidation"].Type);
var nestedValidation = (JArray)jsonNestedError["nestedValidation"];
AssertNestedValidation(nestedValidation, 2); // there are 2 because there are 2 nested content rows
AssertNestedValidation(nestedValidation);
}
private void AssertNestedValidation(JArray nestedValidation, int rows)
private void AssertNestedValidation(JArray nestedValidation)
{
Assert.AreEqual(rows, nestedValidation.Count);
Assert.Greater(nestedValidation.Count, 0);
foreach (var rowErrors in nestedValidation)
{
Assert.AreEqual(JTokenType.Object, rowErrors.Type);
@@ -239,7 +244,7 @@ namespace Umbraco.Tests.Web.Validation
Assert.AreEqual(1, elementTypeErrors.Count); // there is 1 element type in error
foreach (var elementTypeAliasToErrors in elementTypeErrors)
{
Assert.AreEqual("textPage", elementTypeAliasToErrors.Key);
Assert.IsNotEmpty(elementTypeAliasToErrors.Key);
var propErrors = (JObject)elementTypeAliasToErrors.Value;
foreach (var propAliasToErrors in propErrors)
@@ -253,19 +258,15 @@ namespace Umbraco.Tests.Web.Validation
if (nested != null)
{
// recurse
AssertNestedValidation((JArray)nested, 1); // we know this is 1 row
AssertNestedValidation((JArray)nested);
continue;
}
Assert.IsNotEmpty(propError["errorMessage"].Value<string>());
Assert.AreEqual(1, propError["memberNames"].Value<JArray>().Count);
}
}
}
}
}
+1 -1
View File
@@ -54,7 +54,7 @@ namespace Umbraco.Web
ValidationResult result, string propertyAlias, string culture = "", string segment = "")
{
var propValidationResult = new PropertyValidationResult(result);
var propValidationResult = new ContentPropertyValidationResult(result);
var keyParts = new[]
{
@@ -23,7 +23,7 @@ namespace Umbraco.Web.PropertyEditors
}
/// <summary>
/// Return a single <see cref="NestedValidationResults"/> for all sub nested validation results in the complex editor
/// Return a single <see cref="ComplexEditorValidationResult"/> for all sub nested validation results in the complex editor
/// </summary>
/// <param name="value"></param>
/// <param name="valueType"></param>
@@ -36,7 +36,7 @@ namespace Umbraco.Web.PropertyEditors
if (rowResults.Count > 0)
{
var result = new NestedValidationResults();
var result = new ComplexEditorValidationResult();
foreach(var rowResult in rowResults)
{
result.ValidationResults.Add(rowResult);
@@ -55,15 +55,15 @@ namespace Umbraco.Web.PropertyEditors
/// </summary>
/// <param name="rawValue"></param>
/// <returns></returns>
protected IEnumerable<ElementTypeValidationResult> GetNestedValidationResults(IEnumerable<ElementTypeValidationModel> elements)
protected IEnumerable<ComplexEditorElementTypeValidationResult> GetNestedValidationResults(IEnumerable<ElementTypeValidationModel> elements)
{
foreach (var row in elements)
{
var elementTypeValidationResult = new ElementTypeValidationResult(row.ElementTypeAlias);
var elementTypeValidationResult = new ComplexEditorElementTypeValidationResult(row.ElementTypeAlias);
foreach (var prop in row.PropertyTypeValidation)
{
var propValidationResult = new PropertyTypeValidationResult(prop.PropertyType.Alias);
var propValidationResult = new ComplexEditorPropertyTypeValidationResult(prop.PropertyType.Alias);
foreach (var validationResult in _propertyValidationService.ValidatePropertyValue(prop.PropertyType, prop.PostedValue))
{
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Web.PropertyEditors.Validation
{
/// <summary>
/// A collection of <see cref="ComplexEditorPropertyTypeValidationResult"/> for an element type within complex editor represented by an Element Type
/// </summary>
public class ComplexEditorElementTypeValidationResult : ValidationResult
{
public ComplexEditorElementTypeValidationResult(string elementTypeAlias)
: base(string.Empty)
{
ElementTypeAlias = elementTypeAlias;
}
public IList<ComplexEditorPropertyTypeValidationResult> ValidationResults { get; } = new List<ComplexEditorPropertyTypeValidationResult>();
public string ElementTypeAlias { get; }
}
}
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Web.PropertyEditors.Validation
{
/// <summary>
/// A collection of <see cref="ValidationResult"/> for a property type within a complex editor represented by an Element Type
/// </summary>
public class ComplexEditorPropertyTypeValidationResult : ValidationResult
{
public ComplexEditorPropertyTypeValidationResult(string propertyTypeAlias)
: base(string.Empty)
{
PropertyTypeAlias = propertyTypeAlias;
}
public IList<ValidationResult> ValidationResults { get; } = new List<ValidationResult>();
public string PropertyTypeAlias { get; }
}
}
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Web.PropertyEditors.Validation
{
/// <summary>
/// A collection of <see cref="ComplexEditorElementTypeValidationResult"/> for a complex editor represented by an Element Type
/// </summary>
/// <remarks>
/// For example, each <see cref="ComplexEditorValidationResult"/> represents validation results for a row in Nested Content
/// </remarks>
public class ComplexEditorValidationResult : ValidationResult
{
public ComplexEditorValidationResult()
: base(string.Empty)
{
}
public IList<ComplexEditorElementTypeValidationResult> ValidationResults { get; } = new List<ComplexEditorElementTypeValidationResult>();
}
}
@@ -8,12 +8,12 @@ namespace Umbraco.Web.PropertyEditors.Validation
/// <remarks>
/// This clones the original result and then ensures the nested result if it's the correct type
/// </remarks>
public class PropertyValidationResult : ValidationResult
public class ContentPropertyValidationResult : ValidationResult
{
public PropertyValidationResult(ValidationResult nested)
public ContentPropertyValidationResult(ValidationResult nested)
: base(nested.ErrorMessage, nested.MemberNames)
{
NestedResuls = nested as NestedValidationResults;
ComplexEditorResults = nested as ComplexEditorValidationResult;
}
/// <summary>
@@ -22,6 +22,6 @@ namespace Umbraco.Web.PropertyEditors.Validation
/// <remarks>
/// There can be nested results for complex editors that contain other editors
/// </remarks>
public NestedValidationResults NestedResuls { get; }
public ComplexEditorValidationResult ComplexEditorResults { get; }
}
}
@@ -1,45 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Web.PropertyEditors.Validation
{
public class PropertyTypeValidationResult : ValidationResult
{
public PropertyTypeValidationResult(string propertyTypeAlias)
: base(string.Empty)
{
PropertyTypeAlias = propertyTypeAlias;
}
public IList<ValidationResult> ValidationResults { get; } = new List<ValidationResult>();
public string PropertyTypeAlias { get; }
}
public class ElementTypeValidationResult : ValidationResult
{
public ElementTypeValidationResult(string elementTypeAlias)
: base(string.Empty)
{
ElementTypeAlias = elementTypeAlias;
}
public IList<PropertyTypeValidationResult> ValidationResults { get; } = new List<PropertyTypeValidationResult>();
public string ElementTypeAlias { get; }
}
/// <summary>
/// Custom <see cref="ValidationResult"/> that contains a list of nested validation results
/// </summary>
/// <remarks>
/// For example, each <see cref="NestedValidationResults"/> represents validation results for a row in Nested Content
/// </remarks>
public class NestedValidationResults : ValidationResult
{
public NestedValidationResults()
: base(string.Empty)
{
}
public IList<ElementTypeValidationResult> ValidationResults { get; } = new List<ElementTypeValidationResult>();
}
}
@@ -4,15 +4,17 @@ using Newtonsoft.Json.Serialization;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
namespace Umbraco.Web.PropertyEditors.Validation
{
/// <summary>
/// Custom json converter for <see cref="ValidationResult"/> and <see cref="PropertyValidationResult"/>
/// Custom json converter for <see cref="ValidationResult"/> and <see cref="ContentPropertyValidationResult"/>
/// </summary>
/// <remarks>
/// This converter is specifically used to convert validation results for content in order to be able to have nested
/// validation results for complex editors.
/// </remarks>
internal class ValidationResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => typeof(ValidationResult).IsAssignableFrom(objectType);
@@ -34,7 +36,7 @@ namespace Umbraco.Web.PropertyEditors.Validation
var validationResult = (ValidationResult)value;
if (validationResult is NestedValidationResults nestedResult && nestedResult.ValidationResults.Count > 0)
if (validationResult is ComplexEditorValidationResult nestedResult && nestedResult.ValidationResults.Count > 0)
{
var jo = new JObject();
// recurse to write out an array of ValidationResultCollection
@@ -42,7 +44,7 @@ namespace Umbraco.Web.PropertyEditors.Validation
jo.Add("nestedValidation", obj);
jo.WriteTo(writer);
}
else if (validationResult is ElementTypeValidationResult elementTypeValidationResult && elementTypeValidationResult.ValidationResults.Count > 0)
else if (validationResult is ComplexEditorElementTypeValidationResult elementTypeValidationResult && elementTypeValidationResult.ValidationResults.Count > 0)
{
var joElementType = new JObject();
var joPropertyType = new JObject();
@@ -65,11 +67,11 @@ namespace Umbraco.Web.PropertyEditors.Validation
else
{
if (validationResult is PropertyValidationResult propertyValidationResult
&& propertyValidationResult.NestedResuls?.ValidationResults.Count > 0)
if (validationResult is ContentPropertyValidationResult propertyValidationResult
&& propertyValidationResult.ComplexEditorResults?.ValidationResults.Count > 0)
{
// recurse to write out the NestedValidationResults
var obj = JToken.FromObject(propertyValidationResult.NestedResuls, camelCaseSerializer);
var obj = JToken.FromObject(propertyValidationResult.ComplexEditorResults, camelCaseSerializer);
obj.WriteTo(writer);
}
+4 -2
View File
@@ -248,8 +248,10 @@
<Compile Include="PropertyEditors\ComplexEditorValidator.cs" />
<Compile Include="PropertyEditors\ParameterEditors\MultipleMediaPickerParameterEditor.cs" />
<Compile Include="PropertyEditors\RichTextEditorPastedImages.cs" />
<Compile Include="PropertyEditors\Validation\NestedValidationResults.cs" />
<Compile Include="PropertyEditors\Validation\PropertyValidationResult.cs" />
<Compile Include="PropertyEditors\Validation\ComplexEditorElementTypeValidationResult.cs" />
<Compile Include="PropertyEditors\Validation\ComplexEditorPropertyTypeValidationResult.cs" />
<Compile Include="PropertyEditors\Validation\ComplexEditorValidationResult.cs" />
<Compile Include="PropertyEditors\Validation\ContentPropertyValidationResult.cs" />
<Compile Include="PropertyEditors\Validation\ValidationResultConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\BlockEditorConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\BlockListPropertyValueConverter.cs" />