2012-02-21 12 views
5

Trovo soluzioni a metà ovunque ma non riesco a ottenere una risposta reale per questo.MVC3 ValidationAttribute validationContext.memberName è null

Ho creato un attributo di convalida ereditato da ValidationAttribute e IClientValidatable.

Tutto sembra funzionare correttamente e se inserisco un riepilogo di convalida nella pagina viene visualizzato l'errore.

tuttavia non riesco a visualizzare l'errore accanto alla casella di testo relativa alla proprietà.

Penso che questo sia dovuto al fatto che devo aggiungere il nome della proprietà al risultato della convalida.

TUTTO questo è dove non riesce, perché non riesco a ottenere il nome membro dal validationContext.

c'è un modo per consentire che questo accada? O mi sta sfuggendo qualcosa?

public class AdmissionDayCaseAttribute : ValidationAttribute, IClientValidatable 
{ 
    private String DayCaseID; 
    private String AdmissionDateID; 
    private String DischargeDateID; 

    public AdmissionDayCaseAttribute(String DayCaseID, String AdmissionDateID, String DischargeDateID) 
    { 
     this.DayCaseID = DayCaseID; 
     this.AdmissionDateID = AdmissionDateID; 
     this.DischargeDateID = DischargeDateID; 
    } 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     object AdmissionDate = GetPropertyValue(validationContext.ObjectInstance, AdmissionDateID); 
     object DischargeDate = GetPropertyValue(validationContext.ObjectInstance, DischargeDateID); 
     object AdmissionType = validationContext.MemberName == null ? null : GetPropertyValue(validationContext.ObjectInstance, validationContext.MemberName); 
     if (AdmissionDate != null && DischargeDate != null && AdmissionType != null) 
     { 
      if (AdmissionDate.Equals(DischargeDate) && DayCaseID.Equals(AdmissionType.ToString())) 
      { 
       return new ValidationResult(ErrorMessage, new List<String>() { validationContext.MemberName }); 
      } 
     } 
     return ValidationResult.Success; 
    } 
    private object GetPropertyValue(object instance,String propertyName) 
    { 
     Type itype = instance.GetType(); 
     return itype.GetProperty(propertyName).GetValue(instance,null); 
    } 
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     ModelClientValidationRule vr = new ModelClientValidationRule() 
     { 
      ErrorMessage = ErrorMessage, 
      ValidationType = "admissiondaycase" 
     }; 
     vr.ValidationParameters.Add(new KeyValuePair<string, object>("admissiondateid", AdmissionDateID)); 
     vr.ValidationParameters.Add(new KeyValuePair<string, object>("dischargedateid", DischargeDateID)); 
     vr.ValidationParameters.Add(new KeyValuePair<string, object>("daycaseid", DayCaseID)); 
     yield return vr; 
    } 

EDIT/UPDATE

la vista assomiglia a questo -

<tr> 
    <td> 
     @Html.LabelFor(x => x.AdmissionTypeID) 
    </td> 
    <td> 
     @Html.CustomDropDownListFor(a => a.AdmissionTypeID, Lookup.AdmissionTypes,Default.Constant.DROPDOWN) 
     @Html.ValidationMessageFor(a=>a.AdmissionTypeID) 
    </td> 
</tr> 

Non ci javascript o qualsiasi cosa che interagiscono con questo, la sua abbastanza semplice, ma alcuni dettagli in più - questo codice vista è in un modello di visualizzazione, che viene utilizzato IN in una vista parziale

+0

Puoi pubblicare anche tu la tua vista? Hai incluso @ Html.ValidationMessageFor (model => model.PropertyName) oltre alle tue caselle di testo? – CjCoax

+0

Hanno aggiunto la vista, ha sicuramente il messaggio di validazione nella vista - tuttavia lato server il membro non viene visualizzato –

risposta

7

Innanzitutto verificare che il AdmissionDayCaseAttribute è definito correttamente sulla proprietà nel modello.

Quindi invece di restituire validationContext.MemberName restituire validationContext.DisplayName. Se hai modificato il nome utente tramite DsiplayAttribute, potresti fare qualcosa del genere:

var memberName = validationContext.ObjectType.GetProperties() 
    .Where(p => p.GetCustomAttributes(false) 
    .OfType<DisplayAttribute>() 
    .Any(a => a.Name == validationContext.DisplayName)) 
    .Select(p => p.Name).FirstOrDefault(); 

    return new ValidationResult(ErrorMessage, new List<String>() { memberName }); 
+0

Posso capire perché vorrei utilizzare IValidatableObject, tuttavia voglio che valga una proprietà particolare, non il modello stesso . Quanto sopra, anche se utile, non risolve il mio delima di non ottenere il memberName dal validationContext –

+0

Il validationContext.DisplayName è vuoto? –

+0

No il displayname non è vuoto, tuttavia non è uguale al nome della proprietà (poiché anch'io ho dichiarato un attributo di visualizzazione sulla proprietà) –