自定义ValidationAttribute不触发视图模型中的IsValid函数调用

本文关键字:IsValid 函数调用 模型 视图 ValidationAttribute 自定义 | 更新日期: 2023-09-27 18:10:44

我已经创建了自己的自定义ValidationAttribute:

public class UrlValidationAttribute : ValidationAttribute
{
    public UrlValidationAttribute() {}
    public override bool IsValid(object value)
    {
        if (value == null)
            return true;
        var text = value as string;
        Uri uri;
        return (!string.IsNullOrWhiteSpace(text) && 
                Uri.TryCreate(text, UriKind.Absolute, out uri));
    }
}

我正在我的一个模型上使用它,它工作得很好。然而,现在我正试图在视图模型上使用它:

public class DeviceAttribute
{
    public DeviceAttribute(int id, attributeDefinition, String url)
    {
        ID = id;
        Url = url;
    }
    public int ID { get; set; }
    [UrlValidation]
    public String Url { get; set; }
}

视图模型在部分视图中使用如下:

@model List<ICMDB.Models.DeviceAttribute>
<table class="editor-table">
@foreach (var attribute in Model)
{
    <tr>
        @Html.HiddenFor(a => attribute.ID)
        <td class="editor-label">
            @Html.LabelFor(a => attribute.Url)
        </td>
        <td class="editor-field">
            @Html.TextBoxFor(a => attribute.Url)            
            @Html.ValidationMessageFor(a => attribute.Url)
        </td>
    </tr>
}
</table>

由于某些未知的原因,当UrlValidationAttribute的构造函数被触发时,IsValid函数没有被触发。什么好主意吗?

编辑:在进一步的调查中,似乎这正在发生,因为DeviceAttribute视图模型实际上是一个部分的视图模型。整个页面传递一个不同的视图模型,其中包含DeviceAttribute视图模型的列表。因此,当我的控制器操作被调用时,完整的页面视图模型被构造并填充其值,但没有DeviceAttribute视图模型被构造,因此为什么没有验证运行。

自定义ValidationAttribute不触发视图模型中的IsValid函数调用

我建议您使用编辑器模板而不是编写foreach循环。我想你的主视图模型看起来像这样:

public class MyViewModel
{
    public List<DeviceAttribute> Devices { get; set; }
    ...
}

现在在主视图中:

@model MyViewModel
@using (Html.BeginForm())
{
    <table class="editor-table">
        @Html.EditorFor(x => x.Devices)
    </table>
    <input type="submit" value="OK" />
}

,在相应的编辑器模板(~/Views/Shared/EditorTemplates/DeviceAttribute.cshtml)中:

@model DeviceAttribute
<tr>
    @Html.HiddenFor(x => x.ID)
    <td class="editor-label">
        @Html.LabelFor(x => x.Url)
    </td>
    <td class="editor-field">
        @Html.TextBoxFor(x => x.Url)            
        @Html.ValidationMessageFor(x => x.Url)
    </td>
</tr>

POST操作将视图模型收回:

[HttpPost]
public ActionResult Index(MyViewModel model)
{
    ...
}

现在,默认的模型绑定器将成功地绑定视图模型中的所有值并启动验证。