I have created my own custom 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));
}
}
I am using that on one of my models and it works perfectly. However, now I am attempting to use it on a view model:
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; }
}
The view model is used in the partial view like this:
@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>
For some unknown reason, while the constructor for UrlValidationAttribute fires, the IsValid function doesn’t fire. Any ideas?
Edit: On further investigation, it seems this is happening because the DeviceAttribute view model is actually the view model for a partial. The full page is passed a different view model that contains the list of DeviceAttribute view models. So when my controller action is called, the full page view model is constructed and its values filled, but no DeviceAttribute view models are constructed, hence why no validation is run.
I would recommend you using editor templates instead of writing foreach loops. I suppose that your main view model looks something like this:
Now in your main view:
and in the corresponding editor template (
~/Views/Shared/EditorTemplates/DeviceAttribute.cshtml):And your POST action takes the view model back:
Now the default model binder will successfully bind all values in the view model and kick validation.
Here’s a nice blog post about templates.