Open elize-vdr opened 2 years ago
@mikepizzo can they create custom validation rules here?
Hi @ElizabethOkerio, Thank you for looking into this. I saw your comment and in case this may be of value to you on this issue: I built a work-around for now by creating an extenstion of the IEdmModel and creating a new function called ValidationExtended
to replace the original Validation
, and I also added a function called GetEdmModelExtendedRuleSet
in which I create the base ruleset as it is in the original code (base + the additional rules based on the version) then I add a custom ValidationRule that I created that checks for character length 128 (I paste code below). I am not sure if this is the correct way but for now it works. The only problem with this is that the original validation rule for 480 characters is still present, so if it encoutners a name longer than 480 characters it will spit out 2 validation errors, one stating the name is longer than 480 characters as well as the one stating the name is longer than 128 characters, because I cannot remove the 480 character check.
So it would be useful if the ruleset was available to be customized, it can solve some problems.
The code to make all this happen:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Validation;
namespace ODataParser.ParserODataV4
{
public static class EdmValidatorExtensions
{
/// <summary>
/// Validate the <see cref="T:Microsoft.OData.Edm.IEdmModel" /> and all of its properties given certain version.
/// This extension was required to validate the name length of named elements correctly because the .net implementation incorrectly takes the max length of
/// names as 480 where is should be 128 according to the OData specification.
/// </summary>
/// <param name="root">The root of the model to be validated.</param>
/// Indicates whether named elements must be validated with our custom rule that validates
/// for a max length of 128 according to OData specification, this is to allow for the shortcoming in the .net implementation where the
/// rule ValidationRules.NamedElementNameIsTooLong checks for named elements of name length 480 which is incorrect according to OData.
/// If this is false then the normal validation of the .net implementation is done, else we do our own validation against a max length of 128.
/// </param>
/// <param name="errors">Errors encountered while validating the model.</param>
/// <returns>True if model is valid, otherwise false.</returns>
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/Microsoft.OData.Edm.Validation.EdmValidator.Validate?view=netstandard-2.0">`EdmValidator.Validate` on docs.microsoft.com</a></footer>
public static bool ValidationExtended(
this IEdmModel root,
out IEnumerable<EdmError> errors)
{
Version version = root.GetEdmVersion();
if ((object) version == null)
version = EdmConstants.EdmVersionDefault;
return root.Validate(GetEdmModelExtendedRuleSet(version), out errors);
}
/// <summary>
/// Gets the default validation ruleset for the given version with the extended rule added.
/// </summary>
/// <param name="version">The EDM version being validated.</param>
/// <returns>The set of rules to validate that the model conforms to the given version.</returns>
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/Microsoft.OData.Edm.Validation.ValidationRuleSet.GetEdmModelRuleSet?view=netstandard-2.0">`ValidationRuleSet.GetEdmModelRuleSet` on docs.microsoft.com</a></footer>
private static ValidationRuleSet GetEdmModelExtendedRuleSet(Version version)
{
var baseValidationRuleSet = ValidationRuleSet.GetEdmModelRuleSet(version);
ValidationRuleSet customRuleSet = new ValidationRuleSet((IEnumerable<ValidationRule>) baseValidationRuleSet, (IEnumerable<ValidationRule>) new ValidationRule[1]
{
(ValidationRule)ValidationRulesExtension.ExtendNamedElementNameIsTooLong
});
return customRuleSet;
}
}
public static class ValidationRulesExtension
{
/// <summary>
/// Validates that an element name is not too long according to the CSDL spec which is 128 characters.
/// </summary>
public static readonly ValidationRule<IEdmNamedElement> ExtendNamedElementNameIsTooLong = new ValidationRule<IEdmNamedElement>((Action<ValidationContext, IEdmNamedElement>) ((context, item) =>
{
if (IsNullOrWhiteSpaceInternal(item.Name) || item.Name.Length <= 128)
return;
context.AddError(item.Location(), EdmErrorCode.NameTooLong, $"The specified name must not be longer than 128 characters: '{item.Name}' - [{item.GetType()}]");
}));
private static bool IsNullOrWhiteSpaceInternal(string value) => value == null || ((IEnumerable<char>) value.ToCharArray()).All<char>(new Func<char, bool>(char.IsWhiteSpace));
}
}
The IEdmModel.Validate() does not validate the length of an Entity Set's name according to the OData specification rules.
Assemblies affected
Microsoft.Odata.Edm 7.12.1 & Microsoft.OData.Core 7.12.1
Reproduce steps
Validate an OData contract where the EntitySet name is longer than 128 characters, it will pass the validation.
Expected result
If the name of an EntitySet is longer than 128 validation should fail for this name
Actual result
An EntitySet name of length longer than 128 characters passed the IEdmModel.Validate()
Additional detail
According to the OData 4.01 specification the name of an Enity Set is defined as:
Where a
Simple Identier
is defined as:Therefore the maximum length of an Entity Set's name should be 128 characters, if an Entity Set's name is logner than 128 characters it should fail validation, currently the IEdmModel.Validate() allows 480 characters for an EntitySet's name.
For names in OData they are mostly specified as a
Simple Identifier
, these include for example: Nominal Type name: Simple Identifier Namespace alias: Simple Identifier Entity Type Name: Simple Identifier Structural Property name: Simple Identifier Navigation Property name: Simple Identifier Complex Type name: Simple Identifier Enumeration Type name: Simple Identifier TypeDefinition name: Simple Identifier Action name: Simple Identifier Function name: Simple Identifier Parameter name: Simple Identifier Entity Container name: Simple Identifier Entity Set name: Simple Identifier Singleton name: Simple Identifier Term name: Simple IdentifierBut in the .Net OData implementation the validation rule
NamedElementNameIsTooLong
in the classValidationRules
tests for a length of 480. What is the motivation for this? The OData specification states the maximum length for aSimple Identifier
to be 128 and names are all indicated as of typeSimple Identifier
.