2012-02-21 10 views
5

Encuentro soluciones a medias en todas partes pero no puedo obtener una respuesta real para esto.MVC3 ValidationAttribute validationContext.memberName es nulo

He creado un atributo de validación heredado de ValidationAttribute y IClientValidatable.

Todo parece funcionar bien, y si pongo un resumen de validación en la página, aparece el error.

Sin embargo, no puedo ver el error al lado del cuadro de texto relacionado con la propiedad.

Creo que esto se debe a que necesito agregar el nombre de la propiedad al resultado de la validación.

SIN EMBARGO aquí es donde falla, porque no puedo obtener el nombre de miembro de la validationContext.

¿Hay alguna manera de permitir que esto suceda? ¿O me estoy perdiendo algo?

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; 
    } 

EDITAR/ACTUALIZAR

la vista se parece a esto -

<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> 

No No JavaScript o cualquier cosa que interactúan con este, es bastante básicas sin embargo algunos detalles extra - este código de la vista está en una plantilla de vista, que se utiliza EN una vista parcial

+0

¿Puede publicar su vista también? ¿Ha incluido @ Html.ValidationMessageFor (model => model.PropertyName) además de sus cuadros de texto? – CjCoax

+0

He agregado la vista, definitivamente tiene validicationmessagefor en la vista; sin embargo, el memberName no aparece en el servidor –

Respuesta

7

Primero compruebe que el AdmissionDayCaseAttribute está definido correctamente en la propiedad de su modelo.

Luego, en lugar de devolver validationContext.MemberName, devuelve validationContext.DisplayName. Si modificó el nombre del miembro a través del DsiplayAttribute, podría hacer algo como esto:

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

Entiendo por qué usaría IValidatableObject, pero quiero que valide una propiedad en particular, no el modelo en sí. . Lo anterior aunque útil, no soluciona mi delima de no obtener el memberName del validationContext –

+0

¿ValidaContext.DisplayName está vacío? –

+0

No el nombre de visualización no está vacío, sin embargo, tampoco es el mismo el nombre de la propiedad (porque también he declarado un atributo de visualización en la propiedad) –