gifts2017

Передача мутабельного значения с клиента на сервер

Опубликовал Игорь Лазаренко (kbjy) в раздел Программирование - Практика программирования

Исправление ошибки передачи мутабельного значения с клиента на сервер
В своей практике я сталкнулся с такой проблемой. В нашей компании была база УТ, файловый режим работы. Работала замечательно без каких либо нареканий. В один прекрачный день наш системный администратор решил файловый вариант cделать клиент-серверным. Все вроде бы работало нормально. И тут мне звоинт пользователь и говорит, что печатная форма, которой он пользовался все время, вдруг почему то перестала работать. Сообщение у пользователя выходило такое "Не удалось сформировать внешнюю печатную форму! [*]Ошибка при вызове метода контекста (ПредставлениеСерий): Попытка передачи с клиента на сервер мутабельного значения 1-го параметра метода ПредставлениеСерий ().".
Я зашел в интернет и прочитал описание мутабельного значения.
Мутабельное значение - сложный тип данных в объектно-ориентированном программировании, значения которого (как правило - объекты) после своего создания допускают изменение своих свойств.

Прочитав такое описание, я начал искать в чем проблема.Проанализиров код я увидел, что ошибка возникает в момент передачи параметра в функцию, которая получает Наименование характеристики для печатной формы. Вот код, который был в момент возникновения ошибки:
        Запрос = Новый Запрос;
        Запрос.УстановитьПараметр("ТекущийДокумент", Ссылка);
        
        Запрос.Текст =
        "ВЫБРАТЬ
        |    Номер,
        |    Дата,
        |    Контрагент,
        |    Организация,
        |    Товары.(
        |        Номенклатура,
        |        Номенклатура."+ ТекстКодАртикул + " КАК КодАртикул,
        |        Номенклатура.НаименованиеПолное КАК Товар,
        |        КоличествоМест,
        |        Количество,
        |        ЕдиницаИзмерения.Представление  КАК ЕдиницаИзмерения,
        |        ЕдиницаИзмеренияМест.Представление  КАК ЕдиницаИзмеренияМест,
        |        ХарактеристикаНоменклатуры КАК Характеристика,
        |        СерияНоменклатуры КАК Серия
        |    ),
        |    ВозвратнаяТара.(
        |        Номенклатура,
        |        Номенклатура."+ ТекстКодАртикул + " КАК КодАртикул,
        |        Номенклатура.НаименованиеПолное КАК Товар,
        |        Количество,
        |        Номенклатура.ЕдиницаХраненияОстатков.Представление КАК ЕдиницаИзмерения
        |    )
        |ИЗ
        |    Документ.ПриходныйОрдерНаТовары КАК ПриходныйОрдерНаТовары
        |ГДЕ
        |    ПриходныйОрдерНаТовары.Ссылка = &ТекущийДокумент
        |УПОРЯДОЧИТЬ ПО
        |    Товары.НомерСтроки,
        |    ВозвратнаяТара.НомерСтроки";
        
        Шапка = Запрос.Выполнить().Выбрать();
        Шапка.Следующий();
        ВыборкаСтрокТовары = Шапка.Товары.Выбрать();

        Пока ВыборкаСтрокТовары.Следующий() Цикл
            
            Если НЕ ЗначениеЗаполнено(ВыборкаСтрокТовары.Номенклатура) Тогда
                Продолжить;
            КонецЕсли;
            
            Ном = Ном + 1;
            
            ОбластьМакета.Параметры.Заполнить(ВыборкаСтрокТовары);
            ОбластьМакета.Параметры.НомерСтроки = Ном;
            ОбластьМакета.Параметры.Товар       = ВыборкаСтрокТовары.Товар + ФормированиеПечатныхФормСервер.ПредставлениеСерий(ВыборкаСтрокТовары);
            
            ТабДокумент.Вывести(ОбластьМакета);
        КонецЦикла;

Ошибка возникала в момент когда обрабатывалась строка: "ОбластьМакета.Параметры.Товар       = ВыборкаСтрокТовары.Товар + ФормированиеПечатныхФормСервер.ПредставлениеСерий(ВыборкаСтрокТовары);".
Я посмотрел еще раз описание мутабельного значения: "Передавать между клиентом и сервером (в обе стороны) можно только немутабельные значения (т.е. значения которых не могут изменяться): примитивные типы, ссылки, универсальные коллекции, значения системных перечислений, хранилище значения. При попытке передать что-либо другое – аварийное завершение клиентского приложения (даже, если передавать некорректный параметр пытается сервер). Я был удивлен универсальные коллекции можно передавать, а строку универсальной коллекции нет. Поэтому я решил воспользоваться другой универсальной коллекцией, а именно Структурой. В итоге код получился такой:
        Пока ВыборкаСтрокТовары.Следующий() Цикл
            
            Если НЕ ЗначениеЗаполнено(ВыборкаСтрокТовары.Номенклатура) Тогда
                Продолжить;
            КонецЕсли;
            
            Ном = Ном + 1;
            
            Представление = Новый Структура();
            Представление.Вставить("Характеристика", ВыборкаСтрокТовары.Характеристика);
            Представление.Вставить("Серия", ВыборкаСтрокТовары.Серия);
            
            ОбластьМакета.Параметры.Заполнить(ВыборкаСтрокТовары);
            ОбластьМакета.Параметры.НомерСтроки = Ном;
            ОбластьМакета.Параметры.Товар       = ВыборкаСтрокТовары.Товар + ФормированиеПечатныхФормСервер.ПредставлениеСерий(Представление);
            
            ТабДокумент.Вывести(ОбластьМакета);
        КонецЦикла;

Так что если кто то будет сталкиваться с такой же проблемой пусть знает, что строка таблицы значений является мутабельным значением и ее (строку) передавать нельзя. Нужно создать структуру.
Решение же моей проблемы было: в функции "ФормированиеПечатныхФормСервер.ПредставлениеСерий" проверялось условие:

     Если ЗначениеЗаполнено(Выборка.Характеристика)  и (ТипЗнч(Выборка.Характеристика) = Тип("СправочникСсылка.ХарактеристикиНоменклатуры")) Тогда

и условие:

    Если ЗначениеЗаполнено(Выборка.Серия) Тогда

Нужно было создать структуру, где ключом выступали значения проверки условия (Характеристика и Серия), а значениями ключа - Выступали значения Строки данных свойств. Как только это было исправлено печатная форма вновь заработала так как раньше.  

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Василий Казьмин (awk) 06.08.14 14:04
Более правильно:

Представление = Новый Структура();
Представление.Вставить("Характеристика", ВыборкаСтрокТовары.Характеристика);
Представление.Вставить("Серия", ВыборкаСтрокТовары.Серия);



Заменить на:


Представление = Новый Структура("Характеристика, Серия");
ЗаполнитьЗначениеСвойств(Представление, ВыборкаСтрокТовары);
Anchoret; de0nis; AlexPNov; +3 Ответить 1
2. игорь Никик (igo1) 06.08.14 14:38
обойти это по быстрому можно было с помощью функции ЗначениеВСтрокуВнутр(<Значение>) и ЗначениеИзСтрокиВнутр(<Строка>)

Доступность:
Сервер, толстый клиент, внешнее соединение.

<Значение> (обязательный)
Тип: Произвольный.
Преобразуемое значение.
3. Василий Казьмин (awk) 06.08.14 16:11
(2) igo1, Тогда править в двух местах, что не всегда возможно.
4. Игорь Лазаренко (kbjy) 07.08.14 00:37
5. Александр Полтава (Патриот) 13.08.14 14:35
судя по первым предложениям, автор очень спешил поделиться открытием с общественностью))))))
сталкнулся
каких либо
прекрачный
звоинт
почему то
6. Денис Аграновский (de0nis) 15.07.16 15:59
(1) awk, Там опечаточка только:
ЗаполнитьЗначениЯСвойств(), а не значениЕ. А то скопировал и не работает, не пойму где ошибка в двух строках :))
7. Денис Аграновский (de0nis) 15.07.16 16:01
А всё таки из внешней обработки серверный вызов никак не сделать? Что б не тащить лишние процедуры в неё..
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа