Ответ 1
Так же, как сообщение об исключении, которое вы получаете, кажется, что элементы управления HiddenField
не могут быть нацелены стандартными контрольными элементами управления напрямую. Я бы пошел обходным путем CustomValidator
.
Похоже, что валидаторы ASP.NET не проверяют скрытые поля. Я получаю такие сообщения:
Контроль "hiddenField", на который ссылается свойство ControlToValidate "hiddenFieldValidator", не может быть проверен.
У меня есть <asp:HiddenField>
на моей странице, которая получает заполненную клиентскую сторону с некоторым значением. Мне нужно, чтобы это было один раз на сервере, поэтому я добавил ему RequiredFieldValidator
.
И это не сработает!
Как я вижу, в качестве обходного пути я могу:
1. используйте специальный валидатор и не привязывайте его к скрытому полю, просто вызовите метод на OnServerValidate
;
2. Используйте <asp:TextBox>
с стилем CSS display:none
, и он должен работать.
Но я хочу убедиться, что здесь ничего не пропал. Возможно ли или не проверять скрытое поле так же, как и другие текстовые поля? O может быть, третий, более элегантный вариант?
ТИА!
Так же, как сообщение об исключении, которое вы получаете, кажется, что элементы управления HiddenField
не могут быть нацелены стандартными контрольными элементами управления напрямую. Я бы пошел обходным путем CustomValidator
.
@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
).
Вот обходной путь, с которым я столкнулся, потому что, к сожалению, я не смог найти надежного способа проверки с помощью RequiredFieldValidator или CustomValidator из коробки. Если вы оставите свойство ControlToValidate пустым, он кричит на вас. Все, что вам нужно сделать, это создать настраиваемый элемент управления, как показано ниже:
public class HiddenFieldValidator : RequiredFieldValidator
{
protected override bool ControlPropertiesValid()
{
return true;
}
}
Переопределяя корректные проверки свойств, чтобы он всегда возвращал true, он больше не заботится о том, чтобы вы использовали HiddenField, и он вытащит значение из него и проверит без проблем.
Это ответ на решение 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 в проекте веб-сайта
Чтобы расширить решение @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 ', вероятно, будет лучшим выбором, в конечном итоге.