Nel mio progetto MVC ho attributi di convalida personalizzati diversi. Uno di questi è controllare il valore di una proprietà rispetto al valore di un'altra proprietà.C# MVC: richiama dinamicamente il nome della proprietà in base al modello
Come affermato in molti articoli, aggiungo qualcosa come
result.ValidationParameters.Add("otherproperty", _otherPropertyHtml);
result.ValidationParameters.Add("comparetype", _compareType);
result.ValidationParameters.Add("equalitytype", _equalityType);
al ritorno ModelClientValidationRule
oggetto.
Il mio problema ora è che, se la mia proprietà da verificare - è incapsulata in un altro oggetto, la convalida non funzionerà.
Se creo qualcosa come
@Html.TextBoxFor(m => m.ValueOne)
@Html.TextBoxFor(m => m.ValueTwo)
convalida funzionerà bene come rende
data-val-otherproperty="ValueTwo"
Il mio problema è la seguente
@Html.TextBoxFor(m => m.IntermediateObject.ValueOne)
@Html.TextBoxFor(m => m.IntermediateObject.ValueTwo)
Questo renderà due caselle di testo con i nomi IntermediateObject_ValueOne
e IntermediateObject.ValueTwo
. Ma ancora data-val-otherproperty = "ValueOne" per la prima casella di testo.
Come si può ottenere che data-val-otherproperty
abbia sempre il nome corretto dell'altra proprietà?
I miei pensieri sono qualcosa come HtmlHelper <> .NameFor (m => ...) o qualcosa che utilizza la riflessione?
Update 1 - Aggiunto codice come richiesto dai commenti
[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;
}
}
uso a modello a livello sarebbe
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; }
}
E quello che mi metterò nella mia View sarebbe qualcosa di simile
public class ViewModel
{
public MyModel IntermediateObject { get; set; }
}
utilizzato ad es. return View(new ViewModel())
. Così, nel rendering HTML vorrei avere un input
<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" />
ma ho bisogno
<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" />
nel codice HTML in modo javascript-convalida può recuperare correttamente l'altra proprietà.
perché si vuole fare questo?se hai più modelli che hanno così tante somiglianze, dovresti farli condividere una classe genitore, quindi puoi creare una vista basata su quel genitore – DLeh
Ho una struttura richiesta/risposta dove la mia 'Risposta' contiene la' Richiesta ' che verrà pubblicato successivamente. Quindi, nel mio 'View' renderò' @ Html.TextBoxFor (m => m.Request.ValueOne) '. Certo, potrei sempre aggiungere "Request". "Ma non mi piacciono le stringhe magiche, non tutte le parti sono attualmente richieste/risposte e se il nome cambia da" Request "a" RenamedRequest ", nulla funzionerà – KingKerosin
Mostra tutto il codice dell'attributo –