需要在客户端上验证复杂的视图模型。简化为:
public class Survey
{
public List<Question> Questions { get; set; }
}
public class Question
{
public List<Answer> Answers { get; set; }
}
public class Answer
{
public string FieldName { get; set; }
[Required("Please use a number")]
public int Number { get; set; }
}
目前,问题正在客户端上正确验证。但我们需要使用FieldName验证和显示上下文消息,如:
需要“儿童人数”字段。
我实施了一个CustomRequiredAttribute
类(: RequiredAttribute, IClientValidatable
)并用它装饰了Number
属性:
[CustomRequired("{0} is mandatory")]
public int Number { get; set; }
但是,在GetClientValidationRules
方法中,metadata.Model为空。
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
ModelMetadata metadata,
ControllerContext context)
{
// metadata.Model is null here!
ModelMetadata answerFieldNameValue = ModelMetadataProviders.Current
.GetMetadataForProperties(
metadata.Model,
metadata.ContainerType)
.FirstOrDefault(p => p.PropertyName == "FieldName");
// and, therefore, answerFieldNameValue.Model is null too!
}
如果我回到此方法的第一行,并从context.Controller.ViewData.Model
我得到任何Answer
并将其分配给metadata.Model
,那么answerFieldNameValue.Model
将包含正确的字符串,这是答案的字段名称。
如何制作此元数据。模型在到达时具有适当的值?或者任何其他方式来解决这个问题?
答案 0 :(得分:1)
知道了。下面的代码是我的解决方案,其灵感来自BranTheMan who found his way out of a similar problem。
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
private object lastQuestionLabel;
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
ModelMetadata modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
object model = null;
if (modelAccessor != null)
{
model = modelAccessor();
}
if (typeof(SurveyQuestionVM).IsAssignableFrom(containerType) && propertyName == "TreeViewLabel")
{
lastQuestionLabel = model;
}
if (typeof(SurveyAnswerVM).IsAssignableFrom(containerType))
{
modelMetadata.AdditionalValues.Add("QuestionLabel", lastQuestionLabel);
}
return modelMetadata;
}
}