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

时间:2011-10-06 00:56:43

标签: c# .net asp.net-mvc data-annotations

我创建了自己的自定义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视图模型,因此不会运行验证。

1 个答案:

答案 0 :(得分:-1)

我建议您使用编辑器模板而不是编写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)
{
    ...
}

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

这是关于模板的nice blog post