2 Stimmen

Eigenständige Komponente mit Validierung

Ich habe ein Modell namens Foo, das eine Eigenschaft namens MyProp vom Typ Bar hat. Wenn ich dieses Modell an den Controller poste, möchte ich, dass der Model Binder MyProp validiert, weil es das Attribut Erforderlich hat, genauso wie bei einem String. Dies muss in der Bar-Klasse selbst enthalten sein oder als separate Klasse fungieren. Ich habe versucht, das IValidatableObject in der Bar-Klasse zu verwenden, aber es scheint unmöglich zu sein zu überprüfen, ob die Foo-Klasse das Required-Attribut auf MyProp hat? Jetzt bin ich am Ende meiner Möglichkeiten und brauche Hilfe. Unten ist ein Beispielcode für meine Frage.

public class Foo {
    [Erforderlich]
    public Bar MyProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    public string Name { get; set; }
}

2voto

marcus Punkte 8836

Hier ist eine Lösung für mein Problem, bei der ich das integrierte erforderliche Attribut verwenden kann und trotzdem benutzerdefiniertes Verhalten erhalte. Dies ist nur ein Proof-of-Concept-Code.

Das Modell:

public class Page : IPageModel {
    [Display(Name = "Seite", Prompt = "Seitenname angeben...")]
    [Required(ErrorMessage = "Sie müssen einen Seitenname angeben")]
    public PageReference PageReference { get; set; }
}

Der Modell-Binder:

public class PageModelBinder : DefaultModelBinder {
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(bindingContext.ModelType)) {
            var attributes = property.Attributes;
            if (attributes.Count == 0) continue;
            foreach (var attribute in attributes) {
                if (attribute.GetType().BaseType == typeof(ValidationAttribute) && property.PropertyType == typeof(PageReference)) {
                    var pageReference = bindingContext.ModelType.GetProperty(property.Name).GetValue(bindingContext.Model, null) as PageReference;
                    Type attrType = attribute.GetType();
                    if (attrType == typeof (RequiredAttribute) && string.IsNullOrEmpty(pageReference.Name)) {
                        bindingContext.ModelState.AddModelError(property.Name,
                            ((RequiredAttribute) attribute).ErrorMessage);
                    }
                }
            }
        }
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

Der Modell-Binder-Anbieter:

public class InheritanceAwareModelBinderProvider : Dictionary, IModelBinderProvider {
    public IModelBinder GetBinder(Type modelType) {
        var binders = from binder in this
                      where binder.Key.IsAssignableFrom(modelType)
                      select binder.Value;

        return binders.FirstOrDefault();
    }
}

Und zuletzt die globale.asax-Registrierung:

var binderProvider = new InheritanceAwareModelBinderProvider {
    {
        typeof (IPageModel), new PageModelBinder() }
    };
ModelBinderProviders.BinderProviders.Add(binderProvider);

Das Ergebnis: http://cl.ly/IjCS

Was halten Sie von dieser Lösung?

0voto

Jakub Konecki Punkte 44858

Das Problem besteht darin, dass es kein HTML-Feld namens MyProp gibt und MVC keine Validierung für dieses Eigenschaft ausführt.

Ein Weg, um Ihr Ziel zu erreichen, besteht darin, Bar loszuwerden und Eigenschaften von Bar in Foo zu erstellen. Sie können AutoMapper verwenden, um den Installationscode zu minimieren.

Eine weitere Lösung besteht darin, ein benutzerdefiniertes Validierungattribut zu schreiben, das gegen die null Werte validiert, und es anstelle des Required -Attributes zu verwenden.

0voto

Mohayemin Punkte 3801

Lösung 1

Verwenden Sie statt [Erforderlich] eine benutzerdefinierte ValidationAttribute

public class Foo {
    [ErforderlichBar]
    public Bar MeinProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ErforderlichBar : ValidationAttribute {

    public override bool IsValid(object value)
    {
        Bar bar = (Bar)value;

        // validieren. Zum Beispiel
        if (bar == null)
        {
            return false;
        }

        return bar.Name != null;
    }
}

Lösung Zwei:

Fügen Sie einfach Erforderlich den entsprechenden erforderlichen Eigenschaften von Bar hinzu, zum Beispiel

public class Foo {
    //[ErforderlichBar]
    public Bar MeinProp { get; set; }
}

public class Bar {
    [ScaffoldColumn(false)]
    public int Id { get; set; }

    [Erforderlich]
    public string Name { get; set; }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X