Add new validation attribute framework
This commit is contained in:
parent
37477b4df0
commit
57ee784cc6
13
Validation/AlphanumericAttribute.cs
Normal file
13
Validation/AlphanumericAttribute.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NejCommon.Validation;
|
||||||
|
|
||||||
|
public class AlphanumericAttribute : RegexAttribute{
|
||||||
|
public AlphanumericAttribute() : base("^[a-zA-Z0-9]*$","Aabb123"){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
50
Validation/IbanAttribute.cs
Normal file
50
Validation/IbanAttribute.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NejCommon.Validation;
|
||||||
|
|
||||||
|
public class IbanAttribute : RegexAttribute{
|
||||||
|
public const string IbanRegex = @"^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$";
|
||||||
|
public IbanAttribute() : base(IbanRegex,"CZ4622500000000104816258"){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ValidationResult IsValid(object value, ValidationContext ctx)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
return ValidationResult.Success!;
|
||||||
|
var res = base.IsValid(value, ctx);
|
||||||
|
if (res != ValidationResult.Success)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
string iban = value as string;
|
||||||
|
|
||||||
|
string rearranged = iban.Substring(4) + iban.Substring(0, 4);
|
||||||
|
|
||||||
|
// Convert letters to numbers (A=10, B=11, ..., Z=35)
|
||||||
|
StringBuilder numericIban = new StringBuilder();
|
||||||
|
foreach (char ch in rearranged)
|
||||||
|
{
|
||||||
|
if (char.IsLetter(ch))
|
||||||
|
{
|
||||||
|
int charVal = ch - 'A' + 10;
|
||||||
|
numericIban.Append(charVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numericIban.Append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to BigInteger and compute mod 97
|
||||||
|
BigInteger ibanNumber = BigInteger.Parse(numericIban.ToString());
|
||||||
|
|
||||||
|
if(ibanNumber % 97 == 1)
|
||||||
|
return ValidationResult.Success;
|
||||||
|
else
|
||||||
|
return new ValidationResult("Invalid checksum of IBAN");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Validation/NejValidationAttribute.cs
Normal file
19
Validation/NejValidationAttribute.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
namespace NejCommon.Validation;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||||
|
public abstract class NejValidationAttribute : ValidationAttribute
|
||||||
|
{
|
||||||
|
public NejValidationAttribute(string errorMsg = null)
|
||||||
|
{
|
||||||
|
ErrorMessage = errorMsg ?? $"Invalid format";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string ExampleJson { get; }
|
||||||
|
|
||||||
|
public virtual void ApplySchema(OpenApiSchema schema) { }
|
||||||
|
}
|
||||||
42
Validation/NejValidationAttributeFilter.cs
Normal file
42
Validation/NejValidationAttributeFilter.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace NejCommon.Validation;
|
||||||
|
|
||||||
|
public class NejValidationAttributeFilter : ISchemaFilter
|
||||||
|
{
|
||||||
|
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||||
|
{
|
||||||
|
var type = context.Type;
|
||||||
|
var attrOnType = context.MemberInfo?.GetCustomAttributes(typeof(NejValidationAttribute), true)?.Select(a => a as NejValidationAttribute)?.FirstOrDefault();
|
||||||
|
if (attrOnType != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Added examples for: " + context.MemberInfo?.Name);
|
||||||
|
schema.Example = OpenApiAnyFactory.CreateFromJson(attrOnType.ExampleJson);
|
||||||
|
attrOnType.ApplySchema(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
var attrOnType2 = context.ParameterInfo?.GetCustomAttributes(typeof(NejValidationAttribute), true)?.Select(a => a as NejValidationAttribute)?.FirstOrDefault();
|
||||||
|
if (attrOnType2 != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Added examples for: " + context.ParameterInfo?.Name);
|
||||||
|
schema.Example = OpenApiAnyFactory.CreateFromJson(attrOnType2.ExampleJson);
|
||||||
|
attrOnType.ApplySchema(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var prop in type.GetProperties())
|
||||||
|
{
|
||||||
|
if (schema.Properties.TryGetValue(prop.Name, out var pschema))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Schema for: " + prop.Name);
|
||||||
|
var attr = prop.GetCustomAttributes(typeof(NejValidationAttribute), true).Select(a => a as NejValidationAttribute).FirstOrDefault();
|
||||||
|
if (attr != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Added examples for: " + prop.Name);
|
||||||
|
pschema.Example = OpenApiAnyFactory.CreateFromJson(attr.ExampleJson);
|
||||||
|
attrOnType.ApplySchema(schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
Validation/RegexAttribute.cs
Normal file
36
Validation/RegexAttribute.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
namespace NejCommon.Validation;
|
||||||
|
|
||||||
|
public class RegexAttribute : NejValidationAttribute
|
||||||
|
{
|
||||||
|
public override string ExampleJson { get; }
|
||||||
|
public string Pattern { get; }
|
||||||
|
public RegexAttribute(string pattern, string example, string errorMsg = null)
|
||||||
|
{
|
||||||
|
Pattern = pattern;
|
||||||
|
ExampleJson = JsonSerializer.Serialize(example);
|
||||||
|
ErrorMessage = errorMsg ?? $"Invalid format (must match {pattern})";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ValidationResult IsValid(object value, ValidationContext ctx)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
return ValidationResult.Success!;
|
||||||
|
|
||||||
|
var str = value as string;
|
||||||
|
if (string.IsNullOrWhiteSpace(str) || !Regex.IsMatch(str, Pattern))
|
||||||
|
return new ValidationResult(ErrorMessage);
|
||||||
|
return ValidationResult.Success!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ApplySchema(OpenApiSchema schema)
|
||||||
|
{
|
||||||
|
base.ApplySchema(schema);
|
||||||
|
schema.Pattern = Pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user