ASP.NET MVC 2中的MetadataType和客户端验证

时间:2010-03-19 08:34:29

标签: asp.net-mvc validation modelmetadata

继承的属性和MetadataType似乎不适用于ASP.NET MVC 2中的客户端验证。

我们的MetadataTypes验证在服务器上按预期工作,但由于某种原因,它不会为它生成适当的客户端脚本。对于在PersonView上设置了DataAnnotations属性的属性,客户端验证会按预期启动,因此我知道客户端验证是活动的并且它可以正常工作。 是否有人知道是否或如何修复?

以下是我们所拥有的:

public abstract class PersonView
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    [Required] public string PhoneNumber { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string AddressZipCode { get; set; }
    public string AddressCity { get; set; }
    public string AddressCountry { get; set; }
}

[MetadataType(typeof(CustomerViewMetaData))]
public class CustomerView : PersonView {}

[MetadataType(typeof(GuestViewMetaData))]
public class GuestView : PersonView {}

public class GuestViewMetaData
{
    [Required(ErrorMessage = "The guests firstname is required")] public string FirstName { get; set; }
    [Required(ErrorMessage = "The guests lastname is required")] public string LastName { get; set; }
}

public class CustomerViewMetaData
{
    [Required(ErrorMessage = "The customers firstname is required")] public string FirstName { get; set; }
    [Required(ErrorMessage = "The customers lastname is required")] public string LastName { get; set; }
    [Required(ErrorMessage = "The customers emails is required")] public string Email { get; set; }
}

正如你所看到的那样,那里没什么奇特或奇怪的......它可以修复吗? 它是ASP.NET MVC 2中的错误吗?

3 个答案:

答案 0 :(得分:2)

根据微软官方的说法这是ASP.NET MVC 2中的一个错误。我得到了下面的链接,虽然场景不完全相同,但似乎是同样的问题。据我所知,它与inhertited属性和DataAnnotations模型元数据提供程序有关。该链接说他们将尝试解决ASP.NET MVC 3中的问题。

Asp.net MVC 2 RC2: the client side validation does not work with overridden properties

答案 1 :(得分:1)

也许为时已晚,但这是我设法解决这个问题的方法 我创建了一个自定义模型元数据提供程序,它继承自 DataAnnotationsModelMetadataProvider 并覆盖 CreateMetadata 方法。 问题是 containerType 参数中的值指向基类而不是指向继承的类。 这是代码

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName)
    {

        if (modelAccessor != null && containerType != null)
        {                
            FieldInfo container = modelAccessor.Target.GetType().GetField("container");
            if (containerType.IsAssignableFrom(container.FieldType))
                containerType = container.FieldType;
        }

        var modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);



        return modelMetadata;
    }
}

最后,我们必须在Application_Start

的Global.asax中注册此自定义元数据提供程序
ModelMetadataProviders.Current = new CustomModelMetadataProvider();

抱歉我的英文!

答案 2 :(得分:0)

你确定吗?我已经按照您的描述设置了一个ASP.NET MVC 2站点,并且我对基于必需和正则表达式的属性进行了客户端验证。目前它不适用于我自己的验证器(源自ValidationAttribute):

[MetadataType(typeof(AlbumMetadata))]
public partial class Album {}

public class AlbumMetadata {
    [Required(ErrorMessage = "You must supply a caption that is at least 3 characters long.")]
    [MinLength(3, ErrorMessage = "The caption must be at least {0} characters long.")]
    [RegularExpression(@".{3,}")]
    public string Caption { get; set; }
}

MinLength基本上提供了一种更明显的方式来查看正则表达式属性中发生了什么,该属性已添加用于测试)

然后我在视图中有以下内容:

<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<fieldset>
    <legend>Album details</legend>
    <div class="form_row">
        <label for="Caption" class="left_label">Album caption:</label>
        <%= Html.TextBox("Caption", Model.Caption, new { @class = "textbox" })%>
        <%= Html.ValidationMessage("Caption", "*") %>
        <div class="cleaner">&nbsp;</div>
    </div>
    <div class="form_row">
        <label for="IsPublic" class="left_label">Is this album public:</label>
        <%= Html.CheckBox("IsPublic", Model.IsPublic) %>
    </div>
    <div class="form_row">
        <input type="submit" value="Save" />
    </div>
</fieldset>
<% } %>

这导致以下内容输出到表单标签下方的客户端(为清晰起见而格式化):

<script type="text/javascript">
//<![CDATA[
if (!window.mvcClientValidationMetadata)
{ window.mvcClientValidationMetadata = []; }
window.mvcClientValidationMetadata.push({
    "Fields":[
      {"FieldName":"Caption",
       "ReplaceValidationMessageContents":false,
       "ValidationMessageId":"Caption_validationMessage",
       "ValidationRules":[
         {"ErrorMessage":"You must supply a caption that is at least 3 characters long.",
          "ValidationParameters":{},
          "ValidationType":"required"},
         {"ErrorMessage":"The field Caption must match the regular expression \u0027.{3,}\u0027.",
          "ValidationParameters":{"pattern":".{3,}"},
          "ValidationType":"regularExpression"}]
      }],
      "FormId":"form0","ReplaceValidationSummary":false});
//]]>
</script>