C# 基于其他属性更改正则表达式和错误消息

C# 基于其他属性更改正则表达式和错误消息,c#,asp.net-mvc,C#,Asp.net Mvc,在下面的分部类中,我有一个属性Amount和一个RegularExpression属性。这是因为它将字段中的值限制为小数点后2位。但是,“金额”字段有多个位置,小数位数因使用位置而异。CategoryId确定要显示的小数位数。是否有方法基于类CategoryId中的另一个属性更改小数位数限制和ErrorMessage 下面是部分类: [MetadataType(typeof(CS_Parameter_Statewide_AllGrades_ScenarioMetaData))] public p

在下面的分部类中,我有一个属性Amount和一个RegularExpression属性。这是因为它将字段中的值限制为小数点后2位。但是,“金额”字段有多个位置,小数位数因使用位置而异。CategoryId确定要显示的小数位数。是否有方法基于类CategoryId中的另一个属性更改小数位数限制和ErrorMessage

下面是部分类:

[MetadataType(typeof(CS_Parameter_Statewide_AllGrades_ScenarioMetaData))]
public partial class CS_Parameter_Statewide_AllGrades_Scenario
{   
    public int Category { get; set; }

    public class CS_Parameter_Statewide_AllGrades_ScenarioMetaData
    {
        [Required]
        [RegularExpression(@"^\d+.\d{0,2}$", ErrorMessage = "Price can't have more than 2 decimal places")]
        public double Amount { get; set; }
    }

}
以下是视图中显示金额值的循环。如果您查看,您可以看到显示格式将因使用格式方法而有所不同。Format方法返回一个字符串,该字符串确定“TextBoxFor”重载中的格式

        @for (int i = 0; i < Model.AllGradesParamList.Count; i++)
        {
            <tr>
                <td>
                    @Model.CategoryList.Where(x => x.Id == Model.AllGradesParamList[i].CategoryId).Select(x => x.Name).FirstOrDefault()
                    @Html.HiddenFor(model => Model.AllGradesParamList[i].CategoryId)
                </td>
                <td>
                    @Html.TextBoxFor(x => Model.AllGradesParamList[i].Amount, Model.Format(Model.AllGradesParamList[i].Amount, Model.AllGradesParamList[i].CategoryId))
                    @Html.ValidationMessageFor(x => Model.AllGradesParamList[i].Amount)
                </td>
            </tr>
        }

我不确定是否需要编写自定义属性。但是如果我这样做了,有人能提供一个简单但完整的例子,它将像我上面描述的那样工作。

有几个选项;正如您所建议的,您可以编写自己的ValidationAttribute,可能来自RegularExpressionAttribute类等等。实现IValidatableObject接口以进行更复杂的验证可能是一个可行的选择。下面是一个简单的例子:

public class Awesome : IValidatableObject {

    [Required]
    public Int32 Id { get; set; }

    public String Whatever { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        // Perform validation checks...
        // If 'valid' return <null>,
        // and if not, populate the ValidationResult list and return that.
        // The validationContext.ObjectInstance contains what you need, if you
        // cast it properly (see my next example).
    }

}
在MyValidator中,您可以访问Id属性,如下所示:

public class MyValidator {

    public static ValidationResult ValidateThis(String value, ValidationContext context) {
        var awesome = context.ObjectInstance as Awesome;
        if(awesome == null)
            throw new InstanceNotFoundException(
                "This validator only works with an Awesome instance.");

        var id = awesome.Id;

        // Do your thing here, like run a dynamic regular expression match
        // based on the value of 'id'.

        return ValidationResult.Success;
    }
}
对我来说,这段代码并不完美——我不喜欢它假设ObjectInstance是一种特定类型(可能是上下文)。ObjectInstance as IAwesome稍微好一点,所以我可能不建议使用它,但它确实存在


另一方面,不要忘了查看IClientValidable或为自定义验证解决方案添加客户端验证的内容。我想,如果您创建自己的ValidationAttribute,您可能迟早会想实现它。

让它拥有尽可能多的小数,然后添加一个方法以输出x小数,这不是更容易吗?是的,但我试图限制用户的输入实际上IClientValidable部分是我最难处理的部分。你能把它包括在你的答案中吗?也许你可以看看类似的东西。如果你遇到了麻烦,发布一个关于这个问题和你尝试过的解决方案的新问题;
public class MyValidator {

    public static ValidationResult ValidateThis(String value, ValidationContext context) {
        var awesome = context.ObjectInstance as Awesome;
        if(awesome == null)
            throw new InstanceNotFoundException(
                "This validator only works with an Awesome instance.");

        var id = awesome.Id;

        // Do your thing here, like run a dynamic regular expression match
        // based on the value of 'id'.

        return ValidationResult.Success;
    }
}