Home > Blockchain >  Conditional Range Data Annotation in .Net Core
Conditional Range Data Annotation in .Net Core

Time:10-18

I'm trying use data annotations to validate a number in .Net Core. If user check the Type checkbox number must be between 0.5 and 20 else between 0.5 and 100. Is there a way to use range data annotations?

like:

if (type)
 [Range(0.5, 20, ErrorMessage = "<20")]
else
 [Range(0.5, 100, ErrorMessage = "<100")]

or is there any way to do this?

CodePudding user response:

Do this validation using just if.

if (value < 0.5)
  throw new ArgumentOutOfRangeException();

if (type)
{
  if (value > 20)
    throw new ArgumentOutOfRangeException();
}
else 
{
  if (value > 100)
    throw new ArgumentOutOfRangeException();
}

You can't use Attribute as a statement. It's a part of a declaration. Use attributes to add some metadata to (class/field/method/argument/etc) declaration and read this data using reflection.

Data annotations can be used for validation or static analysis.


Read about Attributes in C# and Data annotations.

CodePudding user response:

Technically I prefer to perform this kind of conditional validation on Frontend side. Server side validation is meant usually only for security reasons, as a last resort or for a basic validation: Don't let users inject Potatoes instead of Integers. So if you verify the maximum range boundaries that would be enough if the semantical validation is not critical from a security perspective.

If You insist or think that security can be broken and want to validate all the cases on Server side you can create a custom validation attribute by extending the .NET ValidationAttribute class:

https://docs.microsoft.com/de-de/dotnet/api/system.componentmodel.dataannotations.validationattribute?view=net-5.0

An example about how to use it here: ASP.NET MVC: Custom Validation by DataAnnotation

If You're writing an API in Core .NET yep, as stated by Wootiae You could throw an Exception and let Core .NET return an HTTP code from the range 400 which indicates a "Bad format". This should be done in the API method BODY. Something like this:

if (condition)
    return HttpBadRequest("Bad Request. Out of Range.");

Anyway, frontend code should still enforce this.

Edited

As suggested by pinkfloydx33

CodePudding user response:

You can implement your own custom validation attribute for this case.

Check out https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0#custom-attributes.

You will have to take the bool flag (checkbox on or off) along with the range values as 'inputs' for that custom class.

Should be something like that:

public class NumberRangeByConditionAttribute : ValidationAttribute
{
    float _minRange, _maxRange;

    public NumberRangeByConditionAttribute (bool isChecked, float minWhenChecked, float maxWhenChecked, float minWhenUnchecked, float maxWhenUnchecked)
    {
        if (isChecked) 
        {
            _minRange = minWhenChecked;
            _maxRange = maxWhenChecked;
        }
        else 
        {
            _minRange = minWhenUnchecked;
            _maxRange = maxWhenUnchecked;
        }
    }

    public string GetErrorMessage() =>
        $"Number should be between {_minRange} and {_maxRange}.";

    protected override ValidationResult IsValid(object value,
        ValidationContext validationContext)
    {
        var number = (float)validationContext.ObjectInstance;

        if (number > _maxRange || number < _minRange)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}
  • Related