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

发布于 2024-08-25 13:28:37 字数 1580 浏览 12 评论 0原文

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

我们的 MetadataType 验证在服务器上按预期工作,但由于某种原因,它没有生成适当的客户端脚本为了它。对于在 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 中的错误吗?

Inherited properties and MetadataType does not seem to work with client side validation in ASP.NET MVC 2.

The validation of our MetadataTypes work as expected on the server but for some reason it does not generate the appropriate client scripts for it. Client side validation kicks in as expected for properties with the DataAnnotations attributes set on the PersonView so I know that client side validation is active and that it works. Does anyone know if or how it can be fixed?

Here's what we have:

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; }
}

As you can see, it's nothing fancy or strange in there... Can it be fixed? Is it a bug in ASP.NET MVC 2?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

许一世地老天荒 2024-09-01 13:28:37

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

Asp.net MVC 2 RC2:客户端验证不适用于覆盖的属性

According to a Microsoft official this is a bug in ASP.NET MVC 2. I was given the link below and although the scenario isn't exactly the same, it seems to be the same problem. As far as I can tell it is related to inhertited properties and DataAnnotations model metadata provider. The link says they will try to fix the issue in ASP.NET MVC 3.

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

尐偏执 2024-09-01 13:28:37

也许为时已晚,但这就是我解决这个错误的方法。
我创建了一个自定义模型元数据提供程序,它继承自 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;
    }
}

最后我们必须在 Global.asax 的 Application_Start 中注册这个自定义元数据提供程序

ModelMetadataProviders.Current = new CustomModelMetadataProvider();

对不起我的英语!

Maybe it's too late but this is the way I managed to solve this bug.
I've created a custom model metadata provider that inherits from DataAnnotationsModelMetadataProvider and override the CreateMetadata method.
The problem is that the value in containerType parameter points to the base class instead of pointing to inherited class.
Here is the code

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;
    }
}

And finally we have to register this custom metadata provider in Global.asax at Application_Start

ModelMetadataProviders.Current = new CustomModelMetadataProvider();

Sorry for my English!

场罚期间 2024-09-01 13:28:37

你确定吗?我已经按照您的描述设置了 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"> </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>

Are you sure? I've got a ASP.NET MVC 2 site set up as you describe and I have client side validation of both required and regex based attributes that works fine. It doesn't work with my own validators (that derive from ValidationAttribute) at the moment though:

[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 basically provides a more obvious way to see what's happening in the Regular Expression attribute, which was added for testing)

I then have the following in my view:

<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"> </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>
<% } %>

Which results in the following being output to the client below the form tags (formatted for clarity):

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文