asp: RequiredFieldValidator не проверяет скрытые поля - PullRequest
22 голосов
/ 07 июля 2011

Кажется, что валидаторы ASP.NET не проверяют скрытые поля. Я получаю сообщения, подобные этому:

Элемент управления «hiddenField», на который ссылается свойство ControlToValidate объекта «hiddenFieldValidator», не может быть проверен.

У меня есть <asp:HiddenField> на моей странице, которая заполняется на стороне клиента некоторым значением. Мне нужно, чтобы это присутствовало один раз на сервере, поэтому я добавил RequiredFieldValidator к нему.

И это не работает!

Как мне кажется, в качестве обходного пути я могу:

1. используйте пользовательский валидатор и не привязывайте его к скрытому полю, просто вызовите метод на OnServerValidate;

2. Используйте <asp:TextBox> со стилем CSS display:none, и оно должно работать.

Но я хочу убедиться, что я здесь ничего не упустил. Можно или нет проверить скрытое поле так же, как другие текстовые поля? О, может быть, третий, более элегантный вариант?

ТИА!

Ответы [ 6 ]

36 голосов
/ 06 ноября 2012

@ Ответ Питера заставил меня задуматься, что же на самом деле проверяет ControlPropertiesValid ??

Глядя на тему MSDN , он, среди прочего, ищет ValidationPropertyAttribute .. Хмм, так что если мы просто унаследуем от HiddenField и украсим новый класс с ValidationPropertyAttribute, установленным в Value (для моих целей) тогда «все просто работает». И это так.

using System.Web.UI;
using System.Web.UI.WebControls;

namespace Partner.UserControls {
    [ValidationProperty("Value")]
    public class HiddenField2 : HiddenField {
    } // nothing else required other than ValidationProperty
}

Использование - убедитесь, что вы зарегистрировали сборку, содержащую элемент управления:

<%@ Register Assembly="MyApp" Namespace="MyApp.Controls" TagPrefix="sw" %>

А в вашем контенте Page / UserControl:

<sw:HiddenField2 ID="hidSomeImportantID" runat="server" />

Все валидаторы будут работать с этим. Дополнительным преимуществом является то, что если вы (как и я) используете пользовательскую функцию проверки, вы можете легко оценить HiddenField2.Value, поскольку он содержится в поле args.Value (на стороне сервера это ServerValidateEventArgs).

5 голосов
/ 19 октября 2012

Вот обходной путь, который я нашел, потому что, к сожалению, я не смог найти надежного способа проверки с помощью RequiredFieldValidator ИЛИ CustomValidator из коробки.Если вы оставите свойство ControlToValidate пустым, оно будет кричать на вас.Все, что вам нужно сделать, это создать собственный элемент управления, подобный приведенному ниже:

public class HiddenFieldValidator : RequiredFieldValidator
{
    protected override bool ControlPropertiesValid()
    {
        return true;
    }
}

Переопределяя проверку правильности свойств, чтобы она всегда возвращала true, она больше не заботится о том, что вы используете HiddenField, и она будет тянутьзначение из него и проверить без проблем.

5 голосов
/ 07 июля 2011

Как и в сообщении об исключении, которое вы получаете, кажется, что HiddenField элементы управления не могут быть нацелены стандартными элементами управления напрямую. Я бы пошел с CustomValidator обходным путем.

4 голосов
/ 17 февраля 2014

Чтобы расширить решение @Anders, используя подход CustomValidator, вы можете очень легко получить значение стандартного HiddenField элемента управления, сначала найдя элемент управления, приведя его, а затем используя его UniqueID для просмотраего значение в Page.Request.Form[].


Пример 1. Улучшение валидатора сравнения

Этот пример может быть немного более локальным для вашей реализации.Ниже приведена улучшенная версия вызова метода CompareValidator.EvaluateIsValid(), чтобы добавить поддержку для проверки элементов управления HiddenField.Обратите внимание, что этот метод может быть применен к любому валидатору, вместо того, чтобы заключить HiddenField в пользовательский элемент управления, но метод ControlPropertiesValid также должен быть переопределен, чтобы распознавать и возвращать true при наличии HiddenField.

...

private new string GetControlValidationValue(string id)
{
    var control = this.NamingContainer.FindControl(id); 
    if (control != null)
    {
        if (control is HiddenField) 
        {
            return Page.Request.Form[((HiddenField)control).UniqueID];
        } 
        else 
        {
            return base.GetControlValidationValue(id);
        }
    }
}

protected override bool EvaluateIsValid()
{   
    // removed 'base.' from the call to 'GetControlValidationValue'
    string controlValidationValue = GetControlValidationValue(base.ControlToValidate);
    if (controlValidationValue.Trim().Length == 0)
    {
        return true;
    }
    bool flag = (base.Type == ValidationDataType.Date) && !this.DetermineRenderUplevel();
    if (flag && !base.IsInStandardDateFormat(controlValidationValue))
    {
        controlValidationValue = base.ConvertToShortDateString(controlValidationValue);
    }
    bool cultureInvariantRightText = false;
    string date = string.Empty;
    if (this.ControlToCompare.Length > 0)
    {
        //same as above
        date = GetControlValidationValue(this.ControlToCompare);
        if (flag && !base.IsInStandardDateFormat(date))
        {
            date = base.ConvertToShortDateString(date);
        }
    }
    else
    {
        date = this.ValueToCompare;
        cultureInvariantRightText = base.CultureInvariantValues;
    }
    return BaseCompareValidator.Compare(controlValidationValue, false, date, cultureInvariantRightText, this.Operator, base.Type);
}

...    


Пример 2. Пользовательский динамический валидатор

Этот пример немного сложнее, чем первый.Я регулярно использую настраиваемые динамические валидаторы, которые включаются или отключаются на основе значения другого элемента управления на странице (например, если этот флажок установлен, то это текстовое поле является обязательным; в противном случае его не нужно проверять).Одним из таких валидаторов является мой DynamicRequiredFieldValidator, который наследуется от встроенного RequiredFieldValidator.Динамический валидатор имеет два пользовательских атрибута, ControlThatEnables и ControlValueThatEnables, которые используются для определения, должен ли валидатор быть включен.Ниже приведен фрагмент метода, который определяет, следует ли включать валидатор, но обратите внимание, что, как и выше, этот же метод можно применять для проверки HiddenField без необходимости переноса его в пользовательский элемент управления.

...

var enablingControl = this.NamingContainer.FindControl(ControlThatEnables); 
if (enablingControl != null) 
{
    if (enablingControl is HiddenField)
    {
        var hfValue = Page.Request.Form[((HiddenField)enablingControl).UniqueID];
        isValidatorEnabled = hfValue == ControlValueThatEnables;
    }
}

...


Заключительные мысли

Решение о реализации в конечном итоге остается за вами, как за разработчиком, но я предпочитаюзаключать существующие валидаторы в пользовательские элементы управления, а не в такие элементы, как HiddenFields, TextBoxes, DropDownLists и т. д. в пользовательские элементы управления.У меня есть две основные причины, по которым я предпочитаю это решение: (1) упаковка валидаторов занимает всего несколько минут больше, чем просто добавление ValidationProperty, но обеспечивает значительно большую гибкость и возможность для дальнейшего улучшения валидации .NET, например, можно указатьFindControl вызывает некоторый пользовательский метод, который ищет нужный идентификатор элемента управления в текущем NamingContainer (по умолчанию), а затем расширяет поиск до внешнего Page или родительского элемента NamingContainer, если элемент управления не был найден;(2) ИМХО, если кто-то пытается улучшить валидацию, чище вносить улучшения в валидацию, и, наоборот, если кто-то пытается улучшить WebControl, он чище вносит улучшения в WebControl.

Я полностью уважаю решение @ Скотти и буду первым, кто признает, что если это единственное изменение, которое будет сделано, то его решение сэкономит вам на 5 минут больше, чем это.ИМХО, однако, @Anders ', вероятно, будет лучшим выбором в долгосрочной перспективе.

4 голосов
/ 25 мая 2013

Это ответ на решение Scotty.NET. У меня просто недостаточно репутации, чтобы ответить.

+ 1 к Scotty.NET!

Для тех из нас, кто недостаточно знает о .NET и его компиляции, это может помочь упростить использование его ответа для кого-то другого.

Я хотел использовать его на веб-сайте с использованием Visual Web Developer 2010 Express:

1) Я сохранил полученный HiddenField2 в / App_Code как HiddenField2.cs, с одним изменением -> namespace Controls

2) Затем зарегистрировать элемент управления:

а) На странице <%@ Register Assembly="App_Code" Namespace="Controls" TagPrefix="local" %>

b) В web.config, в system.web> pages> controls, <add tagPrefix="local" namespace="Controls" assembly="App_Code" />

3) И, наконец, конечно, обозначим его как <local:HiddenField2 ...>.

Это делает для забавной раскраски кода. Вероятно, довольно легко улучшить пространство имен, чтобы справиться с этим. Прекрасно работает для меня в моей местной среде; думаю, я не знаю, что не будет проблем на живом сервере.

Дополнительная справка: расширение управления asp.net в проекте сайта

0 голосов
/ 05 апреля 2018

Я бы пошел с CustomValidator клиентской стороной

<script type="text/javascript">
function myMethod(source, args) {
    args.IsValid = document.getElementById("<%= myValue.ClientID %>").value != '';
}
</script>

<asp:HiddenField ID="myValue" runat="server" />
<asp:CustomValidator runat="server" ClientValidationFunction="myMethod" 
                     ErrorMessage="Value missing!" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...