webentwicklung-frage-antwort-db.com.de

MVC-Validierung niedriger/höher als anderer Wert

Wie kann ich ein Modell in MVC.Net, bei dem ich ein Minimum/Maximum akzeptieren möchte, am besten validieren kann?.

Keine individuellen Min/Max-Werte für ein Feld. Separate Felder für einen Benutzer, um ein Minimum/Maximum anzugeben.

public class FinanceModel{
   public int MinimumCost {get;set;}
   public int MaximumCost {get;set;}
}

Ich muss also sicherstellen, dass MinimumCost immer unter den Maximalkosten liegt.

24
Ben Ford

Sie können ein benutzerdefiniertes Validierungsattribut verwenden. Hier ist mein Beispiel mit Datumsangaben. Sie können es jedoch auch mit Ints verwenden.

Hier ist zunächst das Modell:

public DateTime Beggining { get; set; }

    [IsDateAfterAttribute("Beggining", true, ErrorMessageResourceType = typeof(LocalizationHelper), ErrorMessageResourceName = "PeriodErrorMessage")]
    public DateTime End { get; set; }

Und hier ist das Attribut selbst:

public sealed class IsDateAfterAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string testedPropertyName;
    private readonly bool allowEqualDates;

    public IsDateAfterAttribute(string testedPropertyName, bool allowEqualDates = false)
    {
        this.testedPropertyName = testedPropertyName;
        this.allowEqualDates = allowEqualDates;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
        if (propertyTestedInfo == null)
        {
            return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
        }

        var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);

        if (value == null || !(value is DateTime))
        {
            return ValidationResult.Success;
        }

        if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
        {
            return ValidationResult.Success;
        }

        // Compare values
        if ((DateTime)value >= (DateTime)propertyTestedValue)
        {
            if (this.allowEqualDates && value == propertyTestedValue)
            {
                return ValidationResult.Success;
            }
            else if ((DateTime)value > (DateTime)propertyTestedValue)
            {
                return ValidationResult.Success;
            }
        }

        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessageString,
            ValidationType = "isdateafter"
        };
        rule.ValidationParameters["propertytested"] = this.testedPropertyName;
        rule.ValidationParameters["allowequaldates"] = this.allowEqualDates;
        yield return rule;
    }
22
Boranas

Es gibt ein NuGet-Paket namens Foolproof , das diese Anmerkungen für Sie bereitstellt. Das heißt, ein benutzerdefiniertes Attribut zu schreiben ist sowohl ziemlich einfach als auch eine bewährte Methode.

Die Verwendung von Foolproof würde folgendermaßen aussehen:

public class FinanceModel{
   public int MinimumCost {get;set;}

   [GreaterThan("MinimumCost")]
   public int MaximumCost {get;set;}
}
27
Matthew

Für die clientseitige Validierung mithilfe der Parameter allowEqualDates und propertyTested (ergänzen Sie die Antwort von Boranas oben, aber zu lang für einen Kommentar):

// definition for the isdateafter validation rule
if ($.validator && $.validator.unobtrusive) {
    $.validator.addMethod('isdateafter', function (value, element, params) {
        value = Date.parse(value);
        var otherDate = Date.parse($(params.compareTo).val());
        if (isNaN(value) || isNaN(otherDate))
            return true;
        return value > otherDate || (value == otherDate && params.allowEqualDates);
    });
    $.validator.unobtrusive.adapters.add('isdateafter', ['propertytested', 'allowequaldates'], function (options) {
        options.rules['isdateafter'] = {
            'allowEqualDates': options.params['allowequaldates'],
            'compareTo': '#' + options.params['propertytested']
        };
        options.messages['isdateafter'] = options.message;
    });
}

Weitere Informationen: unauffällige Validierung , Jquery-Validierung

6
Nicolas Galler

In VB für ganze Zahlen:

MODEL

<UtilController.IsIntegerGreatherOrEqualThan("PropertyNameNumberBegins", "PeriodErrorMessage")>
        Public Property PropertyNameNumberEnds As Nullable(Of Integer)

VALIDIERUNG 

Public Class IsIntegerGreatherOrEqualThan
        Inherits ValidationAttribute

        Private otherPropertyName As String
        Private errorMessage As String

        Public Sub New(ByVal otherPropertyName As String, ByVal errorMessage As String)
            Me.otherPropertyName = otherPropertyName
            Me.errorMessage = errorMessage
        End Sub

        Protected Overrides Function IsValid(thisPropertyValue As Object, validationContext As ValidationContext) As ValidationResult

            Dim otherPropertyTestedInfo = validationContext.ObjectType.GetProperty(Me.otherPropertyName)

            If (otherPropertyTestedInfo Is Nothing) Then
                Return New ValidationResult(String.Format("unknown property {0}", Me.otherPropertyName))
            End If

            Dim otherPropertyTestedValue = otherPropertyTestedInfo.GetValue(validationContext.ObjectInstance, Nothing)

            If (thisPropertyValue Is Nothing) Then
                Return ValidationResult.Success
            End If

            ''  Compare values
            If (CType(thisPropertyValue, Integer) >= CType(otherPropertyTestedValue, Integer)) Then
                Return ValidationResult.Success
            End If

            ''  Wrong
            Return New ValidationResult(errorMessage)
        End Function
    End Class
1
Dani