0

有一个类(精简版):

public class Parameter
{
    public Guid Id { get; set; }

    public decimal Value { get; set; }
}

在我看来,我有一个参数字典,它们呈现如下:

<input ... name="Parameters[3].Key" type="hidden" value="UniqueParamName" />
<input ... name="Parameters[3].Value.Id" type="hidden" value="395816ad-dfde-11e1-8c36-848f69f05f09" />
<input ... name="Parameters[3].Value.Value" type="text" value="75" />

验证规则将由用户通过一些 GUI 设置并存储在数据库中。我想通过for currentValidationAttribute从数据库中获取 s ,但我看不到任何方法。我还尝试在其中添加属性,其中可以通过一些 [讨厌的] 反射访问容器,但是在为“值”创建元数据时尚未分配“Id”(无论如何,它不可靠)。也许我把整个事情复杂化了,我只想坚持内置的验证。Parameter.IdParameter.ValueModelMetadataProvider.CreateMetadata

public class ExtendedValidationProvider : DataAnnotationsModelValidatorProvider
{
    protected override IEnumerable<ModelValidator> GetValidators(
        ModelMetadata metadata, 
        ControllerContext context, 
        IEnumerable<Attribute> attributes)
    {
        if (metadata.ContainerType == typeof(Parameter) 
            && metadata.PropertyName == "Value")
        {
            Guid parameterId = <some magic code>;
            IEnumerable<Attribute> validationAttributes 
                = db.GetValidationAttributesByParameterId(parameterId);
            return base.GetValidators(metadata, context, validationAttributes);
        }

        return Enumerable.Empty<ModelValidator>();
    }
}
4

2 回答 2

0

在我看来,您应该使用模型验证。模型验证将根据您的模型和应用在模型上定义的验证属性的规则进行验证。

public class MyModel
{
     // This model uses model validation

     [Required(ErrorMessage = "FirstName is a required field.")]
     [StringLength(50, ErrorMessage = "Your FirstName can not exceed 50 characters.")]
     public string FirstName { get; set; }

     [Required(ErrorMessage = "LastName is a required field.")]
     public string LastName { get; set; }
}

这会设置您的模型以进行验证。然后在您的控制器/操作中,您将需要使用 ModelState.IsValid 验证您的ModelState。您也可以在控制器中进行一些自定义“验证”,并使用ModelStateAddModelError添加自定义错误。

如果您想更进一步并创建自己的验证属性,那么您需要做的就是创建一个继承自ValidationAttribute类的新类。这将允许您针对可能位于 DAL 层中的您自己的值或绑定到您的模型的另一个值进行验证。

如果您需要使用全球化,使用模型验证还可以很好地(并且轻松地)设置您,因为有可用的属性允许您选择资源文件,其中包含您可能已定义的各种语言的资源字符串。

我是凭记忆做的,但这应该会引导您朝着正确的方向使用 MVC3 的内置功能并利用模型绑定和模型状态。

高温高压

于 2012-08-15T19:55:24.840 回答
0

我想我可以像这样在自定义 ModelMetadataProvider 中设置容器:

public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor,
    Type containerType, string propertyName)
{
    var metadata = _InnerProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName);
    if (containerType == typeof(Parameter) 
        && !metadata.AdditionalValues.ContainsKey("container"))
    {
        metadata.AdditionalValues["container"] = GetContainer(modelAccessor);
    }

    return metadata;
}

GetContainer是一种使用 [讨厌] 反射的方法(实际上是编译和缓存的表达式)。

最后,验证提供者方面没有神奇的代码:

public class ExtendedValidationProvider : DataAnnotationsModelValidatorProvider
{
    protected override IEnumerable<ModelValidator> GetValidators(
        ModelMetadata metadata, 
        ControllerContext context, 
        IEnumerable<Attribute> attributes)
    {
        if (metadata.ContainerType == typeof(Parameter) 
            && metadata.PropertyName == "Value")
        {
            Guid parameterId = ((Parameter)metadata.AdditionalValues["container"]).Id;
            IEnumerable<Attribute> validationAttributes 
                = db.GetValidationAttributesByParameterId(parameterId);
            return base.GetValidators(metadata, context, validationAttributes);
        }

        return Enumerable.Empty<ModelValidator>();
    }
}
于 2012-08-17T12:42:19.350 回答