C#MVC - 根据模型动态获取属性的名称

时间:2015-08-04 12:42:32

标签: c# asp.net-mvc validation reflection custom-attributes

在我的MVC项目中,我有不同的自定义验证属性。其中之一是检查属性的值与另一个属性的值。

正如许多文章中所述,我添加了类似

的内容
result.ValidationParameters.Add("otherproperty", _otherPropertyHtml);
result.ValidationParameters.Add("comparetype", _compareType);
result.ValidationParameters.Add("equalitytype", _equalityType);

返回ModelClientValidationRule对象。

我现在的问题是,如果我要检查的属性被封装在另一个对象中,验证将无效。

如果我创建类似

的内容
@Html.TextBoxFor(m => m.ValueOne)
@Html.TextBoxFor(m => m.ValueTwo)

验证在渲染时效果很好

data-val-otherproperty="ValueTwo"

我的问题是以下

@Html.TextBoxFor(m => m.IntermediateObject.ValueOne)
@Html.TextBoxFor(m => m.IntermediateObject.ValueTwo)

这将呈现两个名称为IntermediateObject_ValueOneIntermediateObject.ValueTwo的文本框。但仍然是第一个文本框的data-val-otherproperty =“ValueOne”。

如何实现,data-val-otherproperty始终具有其他属性的正确名称?

我的想法类似于HtmlHelper<> .NameFor(m => ...)或使用反射的内容?

更新1 - 根据评论的要求添加了代码

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)]
public class CustomCompareToOther : ValidationAttribute, IClientValidatable
{
    // private backing-field
    private readonly string _otherPropertyName;

    // constructor
    public OemCompareToOther(string otherPropertyName)
    {
        _otherPropertyName = otherPropertyName;
    }

    // implementation of IClientValidatable
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var result = new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.DisplayName),
                ValidationType = "customcomparetoother"
            };

        // add the property-name so it is known when rendered for client-side validation
        result.ValidationParameters.Add("otherproperty", _otherPropertyHtml); // here I would need IntermediateObject.ValueTwo instead of only ValueTwo

        yield return result;
    }
}

模型级别的用法是

public class MyModel
{
    [CustomCompareToOther("ValueOTwo", CompareType.NotEqual, PropertyType.String)]
    public string ValueOne { get; set; }    

    [CustomCompareToOther("ValueTwo", CompareType.NotEqual, PropertyType.String)]
    public string ValueTwo { get; set; }
}

我将在我的视图中添加的内容类似于

public class ViewModel
{
    public MyModel IntermediateObject { get; set; }
}

用于例如return View(new ViewModel())。 所以,在渲染的HTML中我会有一个输入

<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="ValueTwo" />
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="ValueOne" />

但我需要

<input type="text" name="IntermediateObject_ValueOne" id="IntermediateObject.ValueOne" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueTwo" />
<input type="text" name="IntermediateObject_ValueTwo" id="IntermediateObject.ValueTwo" data-val-customcomparetoother-otherpropertyname="IntermediateObject.ValueOne" />

在html中,所以javascript-validation可以正确获取其他属性。

1 个答案:

答案 0 :(得分:2)

您可以使用[Compare("PropertyName")]数据注释。

视图模型中的示例:

[Display(Name = "New Password")]
[DataType(DataType.Password)]
public string NewPassword { get; set; }

[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("NewPassword")]
public string PasswordConfirmation { get; set; }

请记住将System.ComponentModel.DataAnnotations命名空间添加到using语句