Пользовательский атрибут ValidationAttribute не запускает вызов функции isValid в модели представления

#c# #.net #asp.net-mvc #data-annotations

#c# #.net #asp.net-mvc #данные-аннотации

Вопрос:

Я создал свой собственный пользовательский 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) amp;amp; 
                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. Возможно, попробуйте переопределить @protected override ValidationResult isValid(значение объекта, ValidationContext ValidationContext)@ — это метод, который должен быть переопределен для атрибута ValidationAttribute . ПРИМЕЧАНИЕ: убедитесь, что вы вызываете ctor ValidationResult с информацией о члене, найденной в контексте проверки.

2. Пробовал и это, не сработало. Я думаю, это как-то связано с тем фактом, что это находится в частичном представлении, поэтому List<DeviceAttribute> он не передается обратно контроллеру для проверки…

Ответ №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)
{
    ...
}
  

Теперь связующее устройство модели по умолчанию успешно свяжет все значения в модели представления и выполнит проверку.

Вот хороший пост в блоге о шаблонах.