Перейти к содержанию

Кастомная валидация полей с использованием красной рамки

Кастомная валидация полей с использованием красной рамки

Валидация полей с красной рамочкой требует комплексного подхода с написанием нескольких расширений.

  1. Клиентское расширение CardUIExtension.Initialized, которое через control.ValidationFunc добавляет красную рамку, отображаемую по условию на клиенте. Сам факт наличия красной рамки не запрещает сохранение карточки или закрытие строки таблицы (если контрол в таблице).

  2. Если контрол внутри строки таблицы, то можно делать валидацию при закрытии строки. Свойство ValidationFunc в этом случае устанавливает в событии GridViewModel.RowInitializing (контрол получаем как args.RowModel.Controls[“alias”] as GridViewModel), а проверка с выдачей сообщения об ошибке в момент закрытия строки - в событии RowValidating, сообщение об ошибке добавляется в args.ValidationResult.

  3. Необходимо серверное расширение CardStoreExtension.BeforeCommitTransaction, которое выполняет фактическую проверку данных на основании того, что есть на момент сохранения, т.е. когда запрос уйдёт на сервер, откроется транзакция на сохранение, сохранятся данные карточки, но транзакция не закроется (и в этот момент никто не будет видеть данные, т.к. удерживается блокировка на сохранение карточки).

    • В серверном расширении в контексте вам приходит карточка, содержащая только изменённые поля и строки: context.Request.Card. Если в секции нет ни одного изменённого поля, то секции также не будет, поэтому перед обращением надо проверить, что она существует через card.Sections.TryGetValue().

    • Далее вы проверяете, что если среди тех полей секции, которые вам пришли, есть проверяемое поле, то выполняем прямой запрос в БД с проверкой других полей, но только если они не были изменены в том же запросе.

      if (context.Request.Card.Sections.TryGetValue("DocumentCommonInfo", out CardSection commonInfo) && commonInfo.RawFields.ContainsKey("Subject")) { // поле "тема" было изменено }

    • Надо сделать прямой запрос к БД вида db.ExecuteScalar<bool>(“select top 1 1 from Table (inner joins) where (conditions)”, параметры).

    • В условиях WHERE пишем ситуацию, при которой возникает ошибка, и смотрим на результат метода. Например, условие “ТипКонтрагента = ‘юр. лицо’ AND (Телефон IS NULL OR Телефон = ‘’)”

    • Если вернуло true, то есть ошибка. Сообщение об ошибке добавляем в валидацию: context.ValidationResult.AddError(this, “Текст ошибки”). При этом сохранение карточки будет отменено, а транзакция откатится.

  4. Есть другой вариант, но более сложный: сделать расширение CardStoreExtension.AfterBeginTransaction. Оно сможет выполнить проверку и отменить сохранение ещё до того, как данные из карточки будут записаны в незавершённую транзакцию. Но для этого надо получить каждое из актуальных значений полей, которые не пришли с карточкой (т.е. не были изменены) из базы данных. А те, которые пришли с карточкой, должны использоваться вместо значений в базе, когда они есть.

  5. Если используется только толстый клиент, то можно проверку вставить в клиентском расширении CardStoreExtension.BeforeRequest.

    • Этот вариант самый простой, потому что в карточке у вас будут абсолютно все поля в том виде, в каком их сохраняет клиент (т.е. часть полей изменены, часть остались как есть).

    • Проверка простая вида string subject = context.Request.Card.DynamicEntries.Subject, успешно отработает, даже когда тема не менялась.

    • Но это небезопасно, в отличие от сервера, т.к. хитрый пользователь может запустить клиентское приложение с предыдущей версией расширений, где этих проверок ещё нет. А также фактические значения полей в карточке по какой-то причине могли измениться без изменения версии карточки (например, прямым запросом к БД), и тогда проверка может работать с неактуальными данными.

Back to top