it-roy-ru.com

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

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

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

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

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

На мой взгляд, в качестве обходного пути я могу:

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

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

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

ТИА!

22
meme

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

5
Anders Fjeldstad

@ Ответ Питера заставил меня задуматься, что же на самом деле проверяет 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" %>

А в вашем контенте страницы/UserControl:

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

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

36
Scotty.NET

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

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

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

5
Peter

Это ответ на решение 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" %>

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

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

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

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

4
GG2

Чтобы расширить решение @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
Zachary Kniebel

Я бы пошел с 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!" />
0
fubo