0

In netcore 3.1 api service I use attributes for properties from UoN.ExpressiveAnnotations (https://www.nuget.org/packages/UoN.ExpressiveAnnotations.NetCore/):

public class Data
{
    [AssertThat("IsPhone(Phone)")]
    [Required(AllowEmptyStrings = false)]
    [JsonPropertyName("phone_number")]
    public string PhoneNumber { get; set; }
}

For RequiredAttribute I created something like this and it works ok:

    public sealed class RequiredAttribute: System.ComponentModel.DataAnnotations.RequiredAttribute
    {
        private string jsonPropertyName;

        public RequiredAttribute()
        {
            this.ErrorMessage = PropertyErrorMsgs.PropertyRequired;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var attributes = validationContext.ObjectType
                .GetProperty(validationContext.MemberName)
                .GetCustomAttributes(typeof(JsonPropertyNameAttribute), true);
            
            if (attributes != null)
                this.jsonPropertyName = (attributes[0] as JsonPropertyNameAttribute).Name;
            else
                this.jsonPropertyName = validationContext.MemberName;

            return base.IsValid(value, validationContext);
        }

        public override string FormatErrorMessage(string name)
        {
            return string.Format(this.ErrorMessageString, this.jsonPropertyName);
        }
    }

I want to override the error message for every AssertThatAttribute, in the same way: to use jsonPropertyName. But the problem that AssertThatAttribute was created as a sealed class so I can not inherit it. I also try playing with adapters but it did not work for me (maybe because of my mistakes when trying). PropertyErrorMsgs.PropertyRequired comes from ResourceFile (the value: '{0}' json field is required)

What is the best way to do in such conditions?

  • [Related](https://github.com/uon-nuget/UoN.ExpressiveAnnotations.NetCore/issues/30) – canton7 Dec 14 '20 at 16:03
  • You can create a custom attribute, create an instance of `AssertThatAttribute`in the constructor and just passthrough the parameters. From here you can throw a try catch around it and implement your own error handling. – Ben Dec 14 '20 at 16:39
  • @Ben Are you sure about that..? Reflection won't discover that attribute – canton7 Dec 14 '20 at 16:49
  • @canton7 Its just implementing a custom attribute, generally speaking most libraries support this. You will need to follow their guide on doing it but i would be surprised if it wasnt supported especially if they are sealing classes – Ben Dec 14 '20 at 17:32
  • @Ben, I've never seen anyone support that. The code in your custom attribute's ctor will only be run when that attribute is queried, which will only happen if someone is specifically looking for it. OP's UoN.ExpressiveAnnotations library won't be querying types for `MyAssertThatAttribute` unless you somehow tell it to. Even then, I don't know how it would get from where to an instance of `AssertThatAttribute`. – canton7 Dec 14 '20 at 17:33
  • @canton7 you do realise AssertThat itself is a custom attribute? It is implemented using the `IClientModelValidator` interface. You can find information on how to implement your own version here https://stackoverflow.com/questions/36566836/asp-net-core-mvc-client-side-validation-for-custom-attribute To create an instance of `AssertThatAttribute` just use `new AssertThatAttribute();` – Ben Dec 14 '20 at 17:38

0 Answers0