Имя: Пароль:
1C
1С v8
Веб-сервис. Ошибка. Несоответствие типов XDTO: Свойство является списковым
0 freelog
 
06.11.16
15:09
Всем доброго дня!
Вопрос для гуру веб-сервисов.
Имеется следующий код:

Определения = Новый WSОпределения("https://apitest.merlion.com/re/mlservice3?wsdl";, Пользователь, Пароль);
ВебСервис = Новый WSПрокси(Определения, "https://apitest.merlion.com/re/mlservice3";, "MLService", "MLPort");
ВебСервис.Пользователь = Пользователь;
ВебСервис.Пароль = Пароль;
Результат = ВебСервис.getCatalog("All");

При отрабатывании выдает ошибку:

{ВнешняяОбработка.MERLION_API_20.Форма.Форма.Форма(432)}: Ошибка при вызове метода контекста (getCatalog)
    Результат = ВебСервис.getCatalog("All");
по причине:
При вызове веб-сервиса произошла ошибка. Ошибка вызова операции сервиса:  {https://apitest.merlion.com/re/mlservice3}:MLService:getCatalog()
по причине:
При вызове веб-сервиса произошла ошибка. Неизвестная ошибка. Несоответствие типов XDTO:
Свойство является списковым
по причине:
Несоответствие типов XDTO:
Свойство является списковым

Вопрос: чего ему надо? и как пофиксить?
Заранее премного благодарен за конструктивные ответы!
1 freelog
 
07.11.16
15:20
вообще никаких идей?
2 Serginio1
 
07.11.16
15:40
3 Serginio1
 
07.11.16
15:42
4 Serginio1
 
07.11.16
15:43
5 freelog
 
07.11.16
21:53
(2)(3)(4)
Спасибо большое! Это, конечно, крутяк!
Но хотелось бы реализовать только средствами 1С.
Все это затевалось с целью ухода от MSSOAP, а пришли в итоге к .NET.
Кстати, запустить обработку так и не получилось, вываливается ошибка:

{ВнешнийОтчет.Мерлион.Форма.ФормаОтчета.Форма(97)}: Ошибка при вызове конструктора (COMОбъект)
    врап=новый COMОбъект("NetObjectToIDispatch45");
по причине:
-2147221005(0x800401F3): Invalid class string

не подскажете, чего ему надо?
6 Mauser
 
07.11.16
22:11
(4) Когда новая статья на хабре на про Ъ будет?
7 freelog
 
08.11.16
09:51
(6) А по теме есть что сказать?
8 Serginio1
 
08.11.16
09:56
(5) Использование классов .Net в 1С для новичков
Надо зарегистрировать NetObjetToIDispatch45.dll

Добавил нужные DLL и методичку
http://files.rsdn.org/19608/%d0%9c%d0%b5%d1%80%d0%bb%d0%b8%d0%be%d0%bd.zip

(6) Надеюсь в 1С хватит здравого смысла выпустить новую версию Native API, что бы можно было возвращать и передавать в параметрах метода объекты ВК, как это можно делать с COM.

Ну, а так когда выпустят .Net Core 1.1? или если найдется, что то интересное
9 NoiseRND
 
08.11.16
10:01
(1) На сколько я помню, надо передавать в упакованном виде.
А у тебя просто строка передаётся.
Попробуй:
ПараметрXDTO = СериализаторXDTO.ЗаписатьXDTO(Параметр);
10 Serginio1
 
08.11.16
10:47
(5) Кстати несколько некорректное сравнение WCF с MSSOAP.
При этом WCF даже удобнее использовать чем родные средства 1С.
11 freelog
 
08.11.16
11:32
(9) попробовал
Определения = Новый WSОпределения("https://apitest.merlion.com/re/mlservice3?wsdl";, Пользователь, Пароль);
ВебСервис = Новый WSПрокси(Определения, "https://apitest.merlion.com/re/mlservice3";, "MLService", "MLPort");
ВебСервис.Пользователь = Пользователь;
ВебСервис.Пароль = Пароль;
ПараметрXDTO = СериализаторXDTO.ЗаписатьXDTO("All");
Результат = ВебСервис.getCatalog(ПараметрXDTO);

не помогло

(8) все отлично стартануло!..
только вот теперь вопрос: можно ли как-то быстро и красиво преобразовать получаемый com-объект в таблицу значений (окромя метода перебора)
12 freelog
 
08.11.16
11:34
(10) сравнение было только в контексте использование внешних компонент
хотелось реализовать задачу исключительно средствами 1С (это же не 7.7 в конце концов ;) )
13 Serginio1
 
08.11.16
11:55
Не ну конечно можно написать метод. Например здесь http://catalog.mista.ru/public/466196/

можно испоьльзовать Scripting API

str = "public class ВычислительAngleSharp
    |{
     |public  static void ЗаполнитьТз(dynamic ТЗ)
     |   {
     |
     |
     |       var config = Configuration.Default.WithDefaultLoader();
     |       // Устанавливаем адрес страницы сайта
     |       var address = ""https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes"";;
     |       // загружаем страницу и разбираем её
     |       var document = BrowsingContext.New(config).OpenAsync(address).Result;
     |       // Используем CSS селектор для получения строк таблицы с классом  и выбрать из этой строки 3 колонку
     |       var rowSelector = ""tr.vevent"";
     |       var Строки = document.QuerySelectorAll<IHtmlTableRowElement>(rowSelector);
     |       foreach (var str in Строки)
     |       {
     |           dynamic стрТз = ТЗ.Добавить();
     |           var ячейки = str.Cells;
     |           for (int i = 0; i < Math.Min(ячейки.Length, 8); i++)
     |           {
     |
     |               стрТз.Установить(i, ячейки[i].TextContent);
     |
     |           }
     |
     |
     |       }
     |
     |   }
    |}
|
|return  new Action<dynamic>(ВычислительAngleSharp.ЗаполнитьТз);";

            Каталог=Врап.ПолучитьТип("System.AppDomain").CurrentDomain.BaseDirectory;
            КаталогGAC = Path.GetDirectoryName(Врап.ТипКакОбъект(string).Assembly.Location);
            
            ПутьКДлл="d:\Vs2015Programs\ScriptApiDlls\ScriptApiDlls\bin\Debug\";
            КлассДляВычесленияВыражений=Врап.ПолучитьТипИзСборки("ScriptApiDlls.КлассДляВычесленияВыражений",ПутьКДлл+"ScriptApiDlls.dll");
          
            Опции=КлассДляВычесленияВыражений.Опции;

              scr = Опции
                .WithReferences(Каталог + "\AngleSharp.dll", КаталогGAC + "\Microsoft.CSharp.dll")
                //  .WithReferences(typeof(Configuration).Assembly)
                .WithImports("System", "AngleSharp", "AngleSharp.Dom.Html", "AngleSharp.Extensions");

               result = КлассДляВычесленияВыражений.Вычислить(str, scr);
              Тз=новый ТаблицаЗначений;
    Колонки=Тз.Колонки;
    Колонки.Добавить("НомерСерии");
    Колонки.Добавить("НомерСерииВСезоне");
    Колонки.Добавить("Название");
    Колонки.Добавить("Режиссер");
    Колонки.Добавить("Автор");
    Колонки.Добавить("Дата");
    Колонки.Добавить("Код");
    Колонки.Добавить("Просмотров");

    врап.ВыполнитьДелегат(result,Тз);
    
    тз.ВыбратьСтроку();
14 Serginio1
 
08.11.16
11:56
Так и в 1С ты тоже будешь перебирать результат.
15 freelog
 
08.11.16
12:15
(13)ясно, вопрос снимается, как дурацкий
тогда еще один глупый вопрос: как получить название колонки(ключа) в ком-объекте?
http://joxi.ru/12MjxQ3SMMVYzA
16 Serginio1
 
08.11.16
12:16
Можно конечно написать универсальный метод для получения данных свойств или полей получив типы через рефлексию и используя люмбды. Например

var p1 = Expression.Parameter(typeof(ExampleClass));
var p2 = Expression.Parameter(typeof(int));
var body = Expression.Assign(Expression.Property(p1, "IntProp"), p2);
var setter = Expression.Lambda<Action<ExampleClass, int>>(body, p1, p2).Compile();
for (int i = 0; i < 1000000; i++)
    setter(ec, i);
17 Serginio1
 
08.11.16
12:18
Так и получай. Почитай для начала Использование классов .Net для новичков http://catalog.mista.ru/public/448668/

Там совсем немного
18 Serginio1
 
08.11.16
12:34
Получить названия поля можно из документации, можно посмотреть сгенерированные классы в VS. Можно через рефлексию как ты видишь в отладчике.
19 freelog
 
08.11.16
15:58
(17)Почитал, закипел котелок от такого потока информации =)
инфа очень интересная, особенно если вникнуть глубже в классы и их методы.
Но так мы все больше отдаляемся от такой родной, но несовершенной 1С.
Сейчас, хоть убейте, не могу понять, как получить название поля в COM-объекте? Вот как здесь получить наименование второго по счету поля?
http://joxi.ru/12MjxQ3SMMVYzA
Или может каким-то образом весь COM-объект можно преобразовать предварительно в массив, понятный 1С`ке ?
20 Serginio1
 
08.11.16
16:05
Так и получай ЭлементМассива.Description
21 Serginio1
 
08.11.16
16:06
Для каждого стр Из Список Цикл
     Сообщить(стр.Description)
КонецЦикла;
22 Serginio1
 
08.11.16
16:09
Там в отчете ессть метод для тестов
роцедура ПолучитьКаталог(Команда)
    // Вставить содержимое обработчика.
    Клиент= ПолучитьКлиента();
    
    Сообщить(Клиент.helloWorld("Привет"));
    
    Товары= Клиент.getCatalog("N1");
    
    Для Каждого стр из Товары Цикл
        Сообщить("ИД="+стр.ID);
        Сообщить("ИД_Родителя="+стр.ID_PARENT);
        Сообщить("Наименование="+стр.Description);
        Сообщить("===================================");
    КонецЦикла;
    
    
    массив =  Новый COMSafeArray("VT_BSTR", 1);
    массив.SetValue(0,"");
    
    Данные = Клиент.getItems("N10100", массив, "", 0, 2, "");
    
    Для Каждого стр из Данные Цикл
        Сообщить(Врап.ВСтроку(стр));
        Сообщить(стр.NO);
        Сообщить(стр.Name);
        Сообщить(стр.Brand);
        Сообщить(стр.Vendor_part);
        Сообщить(стр.Size);
        Сообщить(стр.EOL);
        Сообщить(стр.Warranty);
        Сообщить(стр.Weight);
        Сообщить(стр.Volume);
        Сообщить(стр.Min_Packaged);
        Сообщить(стр.GroupName1);
        Сообщить(стр.GroupName2);
        Сообщить(стр.GroupName3);
        Сообщить(стр.GroupCode1);
        Сообщить(стр.GroupCode2);
        Сообщить(стр.GroupCode3);
        Сообщить(стр.IsBundle);
        Сообщить(стр.ActionDesc);
        Сообщить(стр.ActionWWW);
        Сообщить(стр.Last_time_modified);
        Сообщить("===================================");
        
    КонецЦикла
    
КонецПроцедуры
23 freelog
 
08.11.16
16:16
(22)Да это я видел.
(20)Все дело в том, что нужно написать функцию, которая бы в цикле оббежала элементы массива и создала колонки в ТЧ с таким же названием.
Отталкиваемся от того, что названия этих колонок предварительно мы не знаем. Поэтому и спрашиваю - КАК получить именно название поля.
24 Serginio1
 
08.11.16
16:39
Через рефлексию.
Что типа.

тип=Врап.ТипКакОбъект(Объеки.GetType());

Свойства= Тип.GetProperties();

Для каждого Свойство из Свойства Цикл
Сообщить(Свойство.Name);
КонецЦикла
25 freelog
 
08.11.16
17:50
(24)интересная конструкция... отладчик на ней начинает просто с ума сходить
но главное, что это работает, спасибо=)
НО теперь чудеса в другом:
Если смотреть на "свойства", то видим все наши атрибуты, как и задумывалось:
http://joxi.ru/52aYeQLu4460k2
А когда начинаем их перебирать в цикле, "свойство" принимает какое-то чудное значение ((
http://joxi.ru/ZrJyjqZu99JeBA
26 dmitryds
 
08.11.16
17:52
(2) во все дырки теперь будешь пихать .NET ?
27 Serginio1
 
08.11.16
17:55
(26) Так посоветуй без .Net. Я делюсь решением, а ты?
28 dmitryds
 
08.11.16
18:00
(27) это не решение, это дополнительные проблемы при поддержке в будущем.
29 Serginio1
 
08.11.16
18:00
(28) Так дай решение! Никаких проблем не имею.
30 freelog
 
08.11.16
18:06
(28)если есть вариант решения для (0) или для (11) - с радостью выслушаю
31 freelog
 
08.11.16
18:54
ну вот... спугнули единственного неравнодушного к страждущим
у кого еще какие идеи есть?
32 Serginio1
 
08.11.16
19:38
(31) Еще из вариантов написать свой вэб сервис прокси
33 freelog
 
08.11.16
19:44
(32)с этого все и начиналось...
На .NET писать?)
34 Serginio1
 
08.11.16
20:10
(33) Да хоть на ПХП, питоне, Node.JS, Java, C++
Выбирай, что хошь
35 freelog
 
21.11.16
16:29
(8).net-гуру подскажите, пожалуйста, как избавиться от такой ошибки? и с чем она связана?
http://joxi.ru/GrqgBeJFQkdKg2
причем возникает НЕ на всех компьютерах...
36 Mauser
 
21.11.16
16:59
(35) Это одна из особенностей использования дотнета в 1С, смирись.

"Используйте мою компоненту и спасибо за рыбу" =)
37 Serginio1
 
23.11.16
10:12
(35) А какая версия .Net установлена?
Возможно сборка дважды загружается из разных каталогов


Убедитесь, что файл является допустимым .NET Framework сборки.
Это исключение, если файл не является допустимым .NET Framework сборки. Для получения дополнительной информации см Ассамблее.
Убедитесь, что сборка или модуль не был загружен дважды с двумя разными свидетельствами.
Доказательства есть множество информации, которая представляет собой вклад политических решений безопасности, например, какие права могут быть предоставлены кодом. Для получения дополнительной информации см GacRemove и доказывания
При использовании методов RegisterAssembly или UnregisterAssembly, проверьте, чтобы убедиться, что имя сборки не длиннее MAX_PATH символов.
Длина имени сборки не может превышать MAX_PATH. Для получения дополнительной информации см RegisterAssembly и UnRegisterAssembly.
При загрузке сателлитной сборки, убедитесь, что указанный CultureInfo соответствует CultureInfo файла.
Спутниковые узлы содержат локализованные ресурсы, которые содержат не локализуемых исполняемый код и ресурсы для одной культуры, которые служат в качестве значения по умолчанию или нейтральной культуры. Для получения дополнительной информации см GetSatelliteAssembly.
38 Serginio1
 
23.11.16
10:27
Возможно, что то поменял в API.
Пересоберу под https://api.merlion.com/re/mlservice3?wsdl
39 Bloood
 
23.11.16
10:33
Эх Мерлион Мерлион. За столько лет не может валидный веб сервис сделать. Приходится людям обходные пути искать... А я же им давал исправленный wsdl. С которым 1с работало стандартными методами. Но походу он им пришелся не по душе.
40 Serginio1
 
23.11.16
10:48
Выложил Новый отчет под https://api.merlion.com
И новый NetObjectToIDispatch45

https://yadi.sk/d/Pe_PqdVczH4Zj

Нужно проставить вы отчете логин пароль
41 Serginio1
 
23.11.16
15:30
На новом АПИ не загружаются данные ни Web client и ClientBase

Проблему с Resolve подправил. Раньше такого не было.
42 Serginio1
 
23.11.16
16:25
Нужно было
https://api.merlion.com/dl/mlservice3?wsdl

загружать
43 Serginio1
 
23.11.16
16:31
Выложил новый апи

https://yadi.sk/d/Pe_PqdVczH4Zj
44 garikxxx
 
24.11.16
03:00
ну, вроде все работает, попробовал и массив передать. остался теперь один вопрос, как вызвать функцию из данной внешней обработки из документа-отчета или как запихнуть функции для работы с API например в общие модули?
Прайс грузится из XML/XLSX это уже давно работает, но некоторые функции хотелось бы вживить в разные документы, обработки.
Конфиг самописанный, формы обычные...
45 Serginio1
 
24.11.16
10:06
Ну вариантов куча.
Начать с Использование классов .Net в 1С для новичков
http://catalog.mista.ru/public/448668/

Основное это получить обертку над .Net классами

врап=новый COMОбъект("NetObjectToIDispatch45");

Дальше нужно загрузить нужную сборку

MLPortClient=врап.ПолучитьТипИзСборки("MerlionApi.com.merlion.api.MLService",ФайлMerlionApi);

Файлы можно складывать в общую папку Например в ProgramFilesX86
Environment=врап.ПолучитьТип("System.Environment");

Каталог=Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);

Можно туда же положить и NetObjetToIDispatch45.dll

Второе это получить клиента

Функция ПолучитьКлиента()
    
    
    myCredentials = Врап.СоздатьОбъект("System.Net.NetworkCredential",Отчет.Логин, Отчет.Пароль);
    // Create a webrequest with the specified URL.
    url = "https://api.merlion.com/dl/mlservice3";;

    client = Врап.СоздатьОбъект(MLPortClient);
    client.Credentials = myCredentials.GetCredential(Врап.СоздатьОбъект("System.Uri",url), "Basic");
    client.PreAuthenticate = true;
    
    return client;
    
КонецФункции


Передавай параметры в метод которые нужны
46 garikxxx
 
29.11.16
18:45
столкнулся еще с проблемой...
получаю список заказов, начинаю их перебирать по очереди из списка полученных и получаю ошибки превышения лимита запросов.
ставил задержку от 2 до 5 секунд, плюс после получения содержимого заказа на его обработку секунда уходит. Сделал чтобы перед запросом выводилось время, т.е. вижу нет превышения 1 запроса в секунду. Даже поддержка подтвердила превышений за день не было.
Но ошибки постоянно валятся. Притом в разных местах. Обработка доходит до конца один раз из 3-4.
Под этим же паролем открыта страничка с заказами, но в момент работы обработки ничего не делал.

Товары= Клиент.getOrderLines(НомерЗаказа,"0");

второй параментр указан как по умолчанию.

У поддрежки одна мысль - "Проверьте, возможно, ошибка закэшировалась у Вас."

Кэш я так понимаю имеется в виду связанный с SOAP. Кто что может подсказать?
47 Serginio1
 
29.11.16
20:39
А как ошибка то выглядит?
48 garikxxx
 
29.11.16
21:47
49 garikxxx
 
29.11.16
21:50
это основное окно ошибки, потом еще вылазит и потом уже 1С.

в ошибке видно что произошло превышение лимитов. 2 обращения в 1 секунду, хотя и мерлион смотрел логи за день ни одного превышения и у меня запросы шли минимум через 3-6 сек
50 garikxxx
 
30.11.16
03:59
короче плюнул и сделал пока через попытку. в случае ошибки приходится нажимать "ок". но зато паузу уменьшил до 1 сек и после "ок" обработка продолжает свою работу - перезапрашивает последний не полученный документ и в итоге доходит до конца.
51 Serginio1
 
30.11.16
13:05
(50) Можешь еще скинуть ошибку?
Кстати, что бы ошибка не вылезало окно ошибки установи
врап.ВыводитьСообщениеОбОшибке=ложь;
52 garikxxx
 
30.11.16
20:12
а что не открывается ссылка? нажми на первую ссылку и когда откроется браузер в конце удали кавычку.
53 Serginio1
 
30.11.16
21:38
(52) Очень маленькое разрешение. Ничего не видно
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн