2015-08-04 12 views
5

In meinem MVC-Projekt habe ich verschiedene benutzerdefinierte Validierungsattribute. Eine davon ist, den Wert einer Eigenschaft gegen den Wert einer anderen Eigenschaft zu überprüfen. C# MVC - Name der Eigenschaft dynamisch abrufen, abhängig vom Modell

Wie in vielen Artikeln erwähnt, füge ich so etwas wie

result.ValidationParameters.Add("otherproperty", _otherPropertyHtml); 
result.ValidationParameters.Add("comparetype", _compareType); 
result.ValidationParameters.Add("equalitytype", _equalityType); 

auf die Rückkehr ModelClientValidationRule Objekt.

Mein Problem ist jetzt, dass - wenn meine Eigenschaft zu überprüfen - in einem anderen Objekt eingekapselt ist, die Validierung nicht funktioniert.

Wenn ich etwas schaffen wie

@Html.TextBoxFor(m => m.ValueOne) 
@Html.TextBoxFor(m => m.ValueTwo) 

Validierung wird gut funktionieren, wie es

macht
data-val-otherproperty="ValueTwo" 

Mein Problem für die ist folgende

@Html.TextBoxFor(m => m.IntermediateObject.ValueOne) 
@Html.TextBoxFor(m => m.IntermediateObject.ValueTwo) 

Dies wird zwei Textfelder mit Namen machen IntermediateObject_ValueOne und IntermediateObject.ValueTwo. Aber immer noch data-val-otherproperty = "ValueOne" für das erste Textfeld.

Wie kann erreicht werden, dass data-val-otherproperty immer den korrekten Namen der anderen Eigenschaft hat?

Meine Gedanken sind so etwas wie HtmlHelper <> .NameFor (m => ...) oder etwas, das Reflexion verwendet?

Update 1 - Added-Code als

durch Kommentare angefordert
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)] 
public class CustomCompareToOther : ValidationAttribute, IClientValidatable 
{ 
    // private backing-field 
    private readonly string _otherPropertyName; 

    // constructor 
    public OemCompareToOther(string otherPropertyName) 
    { 
     _otherPropertyName = otherPropertyName; 
    } 

    // implementation of IClientValidatable 
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var result = new ModelClientValidationRule 
      { 
       ErrorMessage = FormatErrorMessage(metadata.DisplayName), 
       ValidationType = "customcomparetoother" 
      }; 

     // add the property-name so it is known when rendered for client-side validation 
     result.ValidationParameters.Add("otherproperty", _otherPropertyHtml); // here I would need IntermediateObject.ValueTwo instead of only ValueTwo 

     yield return result; 
    } 
} 

Verwendung bei Modell-Ebene

public class MyModel 
{ 
    [CustomCompareToOther("ValueOTwo", CompareType.NotEqual, PropertyType.String)] 
    public string ValueOne { get; set; }  

    [CustomCompareToOther("ValueTwo", CompareType.NotEqual, PropertyType.String)] 
    public string ValueTwo { get; set; } 
} 

wäre Und was ich in meiner Ansicht wie

etwas gesetzt werden würde
public class ViewModel 
{ 
    public MyModel IntermediateObject { get; set; } 
} 

verwendet z return View(new ViewModel()). im gerenderten HTML So würde ich

<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="ValueTwo" /> 
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="ValueOne" /> 

einen Eingang hat, aber ich brauche

<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueTwo" /> 
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueOne" /> 

im html so Javascript-Validierung korrekt die andere Eigenschaft abrufen kann.

+0

warum Sie dies tun wollen?Wenn Sie mehrere Modelle haben, die so viel Ähnlichkeit haben, sollten Sie sie eine Elternklasse teilen lassen, dann können Sie eine Sicht basierend auf diesem Eltern erstellen – DLeh

+0

Ich habe eine Anfrage/Antwort-Struktur aufgebaut, wo meine "Antwort" die "Anfrage" enthält Das wird als nächstes veröffentlicht. Also, in meiner 'Ansicht' rende ich '@ Html.TextBoxFor (m => m.Request.ValueOne)'. Sicher, ich könnte immer "Request" hinzufügen, aber mag keine magischen Strings, nicht alle Teile sind derzeit Request/Response basiert und wenn der Name von "Request" zu "RenamedRequest" wechselt, wird nichts funktionieren – KingKerosin

+0

Alle anzeigen Ihr Attributcode –

Antwort

2

Sie können die Daten Annotation verwenden.

Beispiel in Ihrer Ansicht Modell:

[Display(Name = "New Password")] 
[DataType(DataType.Password)] 
public string NewPassword { get; set; } 

[Display(Name = "Confirm Password")] 
[DataType(DataType.Password)] 
[Compare("NewPassword")] 
public string PasswordConfirmation { get; set; } 

Denken Sie daran, den System.ComponentModel.DataAnnotations Namespace Ihr mit Anweisungen hinzufügen

+0

(Für mich) gibt es keine Option, von benutzerdefinierten Attribut zu ändern Ich muss derzeit 'CompareAttribute' – KingKerosin

Verwandte Themen