0
votes

I am struggling to find an example or solution to validate user input on a Razor Page form control for an IP Address.

The IP Address entered could be any value but I just want to check/verify that the format entered is correct i.e. usual checks against too many digits, incorrect range for an octet beyond .254 etc.

I assumed there would be a built in validation attribute that I could add to the Model Class but unsure whether this would require a NuGet add on.

Correct me if I'm wrong but would assume validating this server side may be the better solution here and reduce code in the long run. But given this is more just for ensuring correct user input rather than being a security feature then am happy to explore all avenues, thanks in advance...

Model Class:

 [Required]
 [Display(Name = "IP Address")]
 public string IpAddress { get; set; }

Razor Page:

 <div class="form-group">
            <label asp-for="ConnectorModel.IpAddress" class="control-label"></label>
            <input asp-for="ConnectorModel.IpAddress" class="form-control" />
            <span asp-validation-for="ConnectorModel.IpAddress" class="text-danger"></span>
        </div>
2

2 Answers

1
votes

In .NET Core, you can simply create a class that inherits from ValidationAttribute. You can see the full details in this doc .

Based on your requirement ,you can create the attribute like :

public class IPAddressAttribute : ValidationAttribute
{

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        YourViewModel yourviewmodel = (YourViewModel)validationContext.ObjectInstance;

        const string regexPattern = @"^([\d]{1,3}\.){3}[\d]{1,3}$";
        var regex = new Regex(regexPattern);
        if (string.IsNullOrEmpty(yourviewmodel.IpAddress))
        {
            return new ValidationResult("IP address  is null");
        }
        if (!regex.IsMatch(yourviewmodel.IpAddress )|| yourviewmodel.IpAddress.Split('.').SingleOrDefault(s => int.Parse(s) > 255)!=null)
        return new ValidationResult("Invalid IP Address");


        return ValidationResult.Success;
    }
}

And in your view model used like :

[IPAddressAttribute]
[Display(Name = "IP Address")]
public string IpAddress { get; set; }
0
votes

After further testing I found I was only able to use the above solution for just a single view model instance, however my app requires the user input validation across multiple pages. Through trial and error I found changing the code as per below allowed me to use the same validation attribute class across multiple razor pages. Credit to Nan in helping me reach the final solution.

View Model:

 [Required]
 [IPAddressAttribute] // This calls the custom validation attribute class
 [StringLength(15)] // No need for a message, custom attribute handles this.
 [Display(Name = "IP Address")]
 public string IpAddress { get; set; }

ValidationAttribute Class:

public class IPAddressAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string IpAddress = (string)value;

        const string regexPattern = @"^([\d]{1,3}\.){3}[\d]{1,3}$";
        var regex = new Regex(regexPattern);
        if (string.IsNullOrEmpty(IpAddress))
        {
            return new ValidationResult("IP address  is null");
        }
        if (!regex.IsMatch(IpAddress) || IpAddress.Split('.').SingleOrDefault(s => int.Parse(s) > 255) != null)
            return new ValidationResult("Invalid IP Address");

        return ValidationResult.Success;
    }
}