Подтвердить что ты не робот

Asp: RequiredFieldValidator не проверяет скрытые поля

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

Контроль "hiddenField", на который ссылается свойство ControlToValidate "hiddenFieldValidator", не может быть проверен.

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

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

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

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

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

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

ТИА!

4b9b3361

Ответ 1

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

Ответ 2

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

Глядя на тему MSDN, он ищет, помимо прочего, ValidationPropertyAttribute.. Hhmm, поэтому, если мы просто выйдем из 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).

Ответ 3

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

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

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

Ответ 4

Это ответ на решение Scotty.NET. Мне просто не хватает репутации, чтобы ответить.

+1 к Scotty.NET!

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

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

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

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

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

b) В web.config, в пределах системных .web > страниц > элементов управления, <add tagPrefix="local" namespace="Controls" assembly="App_Code" />

3) И, наконец, конечно, ссылайтесь на него как <local:HiddenField2 ...>.

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

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

Ответ 5

Чтобы расширить решение @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, которые используются для принятия решения о включении валидатора. Ниже приведен фрагмент метода, который определяет, нужно ли активировать валидатор, но обратите внимание, что, как и выше, этот же метод может быть применен для проверки a 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 validaton, например. можно называть вызовы FindControl некоторым пользовательским методом, который ищет желаемый идентификатор управления в текущем NamingContainer (по умолчанию), а затем расширяет поиск внешним Page или NamingContainer родителем, если элемент управления не был найденный; (2) ИМХО, если кто-то пытается улучшить валидацию, чище сделать улучшения для проверки, и, наоборот, если кто-то пытается улучшить WebControl, чище сделать улучшения для WebControl.

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