.Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д.

Публикация № 466052

Разработка - Практика программирования

.Net HTTPClient multipart/form-data C#

Очень часто нужно при работе с HTTP сервисами или сайтами использовать Асинхронные HTTP запросы, отправку на сервер нескольких файлов, использование сжатия трафика.  Эта статья про то, как этого легко добиться.

Это продолжение статей

Использование классов .Net в 1С для новичков

Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент

1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp

.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

 

Продолжение статьи лежит здесь .Net в 1С. На примере использования HTTPClient,AngleSharp.Удобный парсинг сайтов с помощью библиотеки AngleSharp в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция

Это статья будет полезна не только 7-кам, но и 8-кам. Да, многое умеет HTTPСоединение и HTTPзапрос. Но многого нет.

Например, нет асинхронных запросов, сжатия трафика, отправки составного содержимого и т.д.

В том числе часто можно найти примеры на C# и иногда быстрее их адаптировать с использованием в 1С HTTPClient.

Про HTTPClient можно почитать здесь

https://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/dn440594.aspx

https://msdn.microsoft.com/ru-ru/library/system.net.http.httpclient(v=vs.118).aspx

Итак, начнем.

Клиент=Врап.СоздатьОбъект(HttpClient);
ДанныеРесурса=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx").Result;

Сообщить(Врап.ВСтроку(ДанныеРесурса));

Все очень просто. Но это умеет и HTTPСоединение.

Для начала объявим используемые типы при открытии.

врап=новый COMОбъект("NetObjectToIDispatch45");
	HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
	HttpClientHandler = врап.ПолучитьТип("System.Net.Http.HttpClientHandler");

	// Контенты для Post
	
	MultipartFormDataContent=Врап.ПолучитьТип("System.Net.Http.MultipartFormDataContent");
	StreamContent  =Врап.ПолучитьТип("System.Net.Http.StreamContent");
	StringContent  =Врап.ПолучитьТип("System.Net.Http.StringContent");
	ByteArrayContent=Врап.ПолучитьТип("System.Net.Http.ByteArrayContent");
	FormUrlEncodedContent =Врап.ПолучитьТип("System.Net.Http.FormUrlEncodedContent");

	 DecompressionMethods= Врап.ПолучитьТип("System.Net.DecompressionMethods");

    ServicePointManager=врап.ПолучитьТип("System.Net.ServicePointManager");
	Dictionary=Врап.ПолучитьТип("System.Collections.Generic.Dictionary`2[System.String,System.String]");
	StringBuilder=Врап.ПолучитьТип("System.Text.StringBuilder");
    String=Врап.ПолучитьТип("System.String");	
	HttpUtility=Врап.ПолучитьТипИзСборки("System.Web.HttpUtility","System.Web.dll");
	
	
	// Сборку AngleSharp.dll поместить в каталог программы
	//Для использования Scripting Api
    КатаогПрограммы=Врап.ПолучитьТип("System.AppDomain").CurrentDomain.BaseDirectory;
	ИмяСборкиAngleSharp=Врап.ПолучитьТип("System.IO.Path").Combine(КатаогПрограммы,"AngleSharp.dll");
	AngleSharp_Configuration=Врап.ПолучитьТипИзСборки("AngleSharp.Configuration",ИмяСборкиAngleSharp);
	
	IO_File =Врап.ПолучитьТип("System.IO.File");
	Encoding=Врап.ПолучитьТип("System.Text.Encoding");

// В релизе нужно отлавливать ошибки	
//	врап.ВыводитьСообщениеОбОшибке=ложь;

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

Начнем с асинхронного программирования. Часто нужно использовать долгие запросы, или нужно одновременно использовать несколько запросов. К сожалению, 1С этого не позволяет. Поэтому в свой разработке я постарался исправить этот недочет.

Выполнитель=Врап.ПолучитьАсинхронныйВыполнитель();
ДобавитьОбработчик Выполнитель.ПриОкончанииВыполненияЗадачи, ПриОкончанииВыполнения;

//Обработчик события выглядит так
Процедура ПриОкончанииВыполнения(Задача,ДанныеКЗадаче)

    // Обязательно нужно отлавливать ошибку в 1С
    // Иначе она передается в .Net где обрабатывается там
    Попытка
Так как задача может завершиться с ошибкой
Мы должны проверить, и если ошибка нужно предпринять какие то действия
        Если (Задача.IsFaulted) Тогда  // Ошибка выполнения

            Сообщить("Ошибка "+Врап.ВСтроку(Задача.Exception));
            Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));

        иначе
            Сообщить("=====Выполнена задача ====");
            Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));
            Сообщить(Врап.ВСтроку(Задача.Result));


        КонецЕсли;

    Исключение
        Сообщить("Ошибка в процедуре");
        Сообщить(ОписаниеОшибки());
    КонецПопытки

КонецПроцедуры

Вызываем задачу так

    Клиент=Врап.СоздатьОбъект(HttpClient);
    Задача=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx");
    Выполнитель.Выполнить(задача,ТекущаяДата());

 

 Для тестов я сделал тестовый Вэб сервис на ASP.Net

 

Для теста  множества асинхронных запросов сделал функцию

       [HttpGet]
        public async Task<string> GetIdAsync(string id)
        {
            await Task.Delay(1000);
            return id;
 

        }

Имитируем задержку в 1 секунду. Например, нам нужно выполнить 100 запросов.

Процедура TestAsyncНажатие(Элемент)
	// Вставить содержимое обработчика.

    handler = врап.СоздатьОбъект(HttpClientHandler);

    Сообщить(ServicePointManager.DefaultConnectionLimit);
    ServicePointManager.DefaultConnectionLimit=100;


	        Клиент = Врап.СоздатьОбъект(HttpClient,handler);
// Использование заголовков не обязательно
// В данном случае это пример их использования
	        Клиент.DefaultRequestHeaders.Connection.Add("keep-alive");
			CacheControl=Врап.СоздатьОбъект("System.Net.Http.Headers.CacheControlHeaderValue");
			CacheControl.MaxAge = Врап.ПолучитьТип("System.TimeSpan").Zero;
            Клиент.DefaultRequestHeaders.CacheControl = CacheControl;
            Клиент.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,*/*");
            Клиент.DefaultRequestHeaders.Add("Accept-Language", "ru-Ru");
            Клиент.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
			
		    uriSources =ПолучитьСтрокуЗапроса("http://localhost.fiddler:40320/api/values/GetIdAsync/");
	
           Клиент.BaseAddress =Врап.СоздатьОбъект("System.Uri",uriSources); 
		   
		   Выполнитель=Врап.ПолучитьАсинхронныйВыполнитель();
	ДобавитьОбработчик Выполнитель.ПриОкончанииВыполненияЗадачи, ПриОкончанииВыполнения;
	
	ВыполненоЗадач=0;
    МассивОтветов=новый массив;
	
	stopWatch = Врап.СоздатьОбъект("System.Diagnostics.Stopwatch");
	stopWatch.Start();
			Для сч=1 По 100 Цикл
			
				Задача=Клиент.GetStringAsync(СокрЛП(сч));

	             Выполнитель.Выполнить(задача,ТекущаяДата());

			
			 КонецЦикла; 
			 
КонецПроцедуры

Процедура ВывестиВремя(stopWatch,толькоВремя=ложь)
	ts = stopWatch.Elapsed;
	String=Врап.ПолучитьТип("System.String");
	// Format and display the TimeSpan value.
	elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
	ts.Hours, ts.Minutes, ts.Seconds,
	ts.Milliseconds / 10,0);
	Сообщить(elapsedTime);
	Если толькоВремя Тогда
		возврат
	КонецЕсли;
	Для каждого стр  Из МассивОтветов Цикл
	
		   сообщить(стр);
	
	КонецЦикла; 
КонецПроцедуры	

Процедура ПриОкончанииВыполнения(Задача,ДанныеКЗадаче)
	
	// Обязательно нужно отлавливать ошибку в 1С
	// Иначе она передается в .Net где обрабатывается там
	ВыполненоЗадач=ВыполненоЗадач+1;
	
	
	
	Попытка
		
		Если (Задача.IsFaulted) Тогда  // Ошибка выполнения
			
			Сообщить("Ошибка "+Врап.ВСтроку(Задача.Exception));
			Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));
			
		иначе
			//Сообщить("=====Выполнена задача ====");
			//Сообщить("Данные к задаче "+Врап.ВСтроку(ДанныеКЗадаче));
			//Сообщить(Врап.ВСтроку(Задача.Result));
			МассивОтветов.Добавить(Задача.Result);
                          Если ВыполненоЗадач=100 Тогда
		
		             ВывестиВремя(stopWatch)	
		
	                  КонецЕсли; 
		КонецЕсли; 
		
	Исключение
		Сообщить("Ошибка в процедуре");
		Сообщить(ОписаниеОшибки());
	КонецПопытки	
	
КонецПроцедуры

Если бы при синхронном выполнении нам понадобилось бы минимум 100 сек, то при асинхронном уходит порядка 1,5 сек.

Отдельно нужно отметить использование ServicePointManager. Более подробно можно посмотреть здесь

Почему одновременно происходит только два соединения с сайтом

Тест сетевой нагрузки


Есть еще вариант дождаться всех запросов

 

лист=Врап.СоздатьОбъект("System.Collections.Generic.List`1[System.Threading.Tasks.Task]");
	Для сч=1 по 10 Цикл
           Задача=Клиент.GetStringAsync(СокрЛП(сч));
           лист.Add(задача); 
       КонецЦикла;

      Task=Врап.ПолучитьТип("System.Threading.Tasks.Task");
      массив=лист.ToArray(); 
      Task.WaitAll(массив);
      Для каждого задача из лист Цикл 
         Сообщить(задача.Result); 
      КонецЦикла


Но здесь нужно учитывать, что например в выполнитель испольует контекс синхронизации, что может приводить к блокировкам  https://habrahabr.ru/post/257221/

Проверил асинхронные методы HttpClient не зависят от контекста синхронизации.


Перед тем как перейти к использованию multipart/form-data, покажу примеры отправки Post запросов.

Процедура ЗакрытьРесурс(Ресурс) 
	Врап.ПолучитьИнтерфейс(Ресурс,"IDisposable").Dispose();
КонецПроцедуры

Функция ПолучитьСтрокуОтвета(стрОриг)

Стр=СтрЗаменить(стрОриг,"""","");
возврат СтрЗаменить(стр,"\r\n",Символы.ПС);
	

КонецФункции // ПолучитьСтрокуОтвета()

Функция ПолучитьСтрокуЗапроса(uriSources)
	Если не ФлИспользоватьФиддлер Тогда
		возврат СтрЗаменить(uriSources,".fiddler","");
	КонецЕсли;
	
	Возврат uriSources
	КонецФункции
Функция ВыполнитьПост(uriSources,Клиент)

  //  Контент=Врап.СоздатьОбъект("System.Net.Http.StringContent","Тестовая Строка",Encoding.UTF8,"text/plain");
    Контент=Врап.СоздатьОбъект("System.Net.Http.StringContent","Тестовая Строка "+uriSources);
	резулт=Клиент.PostAsync(uriSources,Контент).Result;
	 
	
	Сообщить("===================================");
	
	Сообщить(резулт.IsSuccessStatusCode);
	Сообщить(Врап.Встроку(резулт.StatusCode));

	стр=резулт.Content.ReadAsStringAsync().Result;
   Сообщить(ПолучитьСтрокуОтвета(стр));
	

КонецФункции // ВыполнитьПост()
 
Процедура TestGetНажатие(Элемент)
	// Вставить содержимое обработчика.
	 HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
	
	HttpUtility=Врап.ПолучитьТипИзСборки("System.Web.HttpUtility","System.Web.dll");

	
	Попытка

	uriSources =ПолучитьСтрокуЗапроса("http://localhost.fiddler:40320/api/values/");
   	handler = врап.СоздатьОбъект(HttpClientHandler);
	
    cookieContainer = Врап.СоздатьОбъект("System.Net.CookieContainer");
  
   handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate);
// Используем cookieContainer для задания куков со стороны клиента. Куки со стороны сервера автоматически сохраняются.
cookieContainer.Add(Врап.СоздатьОбъект("System.Net.Cookie","TestCookie", "TruLyaLya", "/", "localhost"));
   handler.CookieContainer=cookieContainer;
   handler.UseCookies=истина;

	    Клиент = Врап.СоздатьОбъект(HttpClient,handler);
	    DefaultRequestHeaders=Клиент.DefaultRequestHeaders;
	    DefaultRequestHeaders.Connection.Add("keep-alive");
			CacheControl=Врап.СоздатьОбъект("System.Net.Http.Headers.CacheControlHeaderValue");
			CacheControl.MaxAge = Врап.ПолучитьТип("System.TimeSpan").Zero;
            DefaultRequestHeaders.CacheControl = CacheControl;
			
            DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,*/*");
            DefaultRequestHeaders.Add("Accept-Language", "ru-Ru");
            DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");


        //Использум BaseAddress, что бы в дальнейшем задавать адрес только ресурса
	Клиент.BaseAddress =Врап.СоздатьОбъект("System.Uri",uriSources);
        Стр=Клиент.GetStringAsync("GetHeaders").Result;
// В данном случае запрос отправится
//
	Сообщить(ПолучитьСтрокуОтвета(стр));
	
	ВыполнитьПост("SendStr",Клиент);
	ВыполнитьПост("SendStr2",Клиент);
	
	 ЗакрытьРесурс(Клиент);
	 
 Исключение
	 Сообщить(ОписаниеОшибки());
	 
	 Если Врап.ПоследняяОшибка<>Неопределено Тогда
	 
	 	ПоказатьПредупреждение(,Врап.ПоследняяОшибка.Message);

	 
	 КонецЕсли; 
			Врап.ВывестиПоследнююОшибку();

 КонецПопытки
 

	
КонецПроцедуры

Процедура ПослатьStreamНажатие(Элемент)
	// Вставить содержимое обработчика.
	uriSources =ПолучитьСтрокуЗапроса("http://localhost.fiddler:40320/api/values/SendStream");
	
	

	Клиент=Врап.СоздатьОбъект(HttpClient);

	// Создаем поток в памяти и записываем в него данные строки в кодировке UTF8
        поток=врап.СоздатьОбъект(MemoryStream,Encoding.UTF8.GetBytes("Отсылаемая строка"));


	
	Контент=Врап.СоздатьОбъект(StreamContent,поток);
	резулт=Клиент.PostAsync(uriSources,Контент).Result;
	 
	
	Сообщить("===================================");
	
	Сообщить(резулт.IsSuccessStatusCode);
	Сообщить(Врап.Встроку(резулт.StatusCode));

	стр=резулт.Content.ReadAsStringAsync().Result;
        Сообщить(ПолучитьСтрокуОтвета(стр));
   
       ЗакрытьРесурс(Клиент);

КонецПроцедуры

Иногда нужно не только отправить но и получить куки


 

	// Вставить содержимое обработчика.
	cookieContainer = Врап.СоздатьОбъект("System.Net.CookieContainer");
	
  handler=Врап.СоздатьОбъект(HttpClientHandler);
  handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ;
  handler.CookieContainer=cookieContainer;
  
  

	Клиент = Врап.СоздатьОбъект(HttpClient,handler);
    uriSources ="http://www.telerik.com";
    Ури=Врап.СоздатьОбъект("System.Uri",uriSources);
	Клиент.BaseAddress =Ури;
	
   Стр=Клиент.GetStringAsync("/UpdateCheck.aspx?isBeta=False").Result;
   
   // Пострим все куки присоединенные по этому аресу
    Куки = cookieContainer.GetCookies(Ури);
	Для  каждого кук  из Куки Цикл
		Сообщить(кук.Name + ": " + кук.Value);
	КонецЦикла;

	// Можем получить конкретное значение
	кук=Куки.get_Item("sid");
	Сообщить(кук.Name + ": " + кук.Value);


Отправляемый контекст можно задавать пятью способами

  • MultipartFormDataContent,
  • StreamContent,
  • StringContent,
  • ByteArrayContent,
  • FormUrlEncodedContent

Выбирайте тот, который удобен. FormUrlEncodedContent это аналог отправики данных Form при Post Submit.

Теперь перейдем к отправке multipart/form-data. 

Процедура Multi_PartНажатие(Элемент)
	// Вставить содержимое обработчика.
	uriSources =ПолучитьСтрокуЗапроса("http://localhost.fiddler:40320");
	//uriSources ="http://localhost:40320";
	HttpClient=Врап.ПолучитьТипИзСборки("System.Net.Http.HttpClient","System.Net.Http.dll");
	MultipartFormDataContent=Врап.ПолучитьТип("System.Net.Http.MultipartFormDataContent");

	
	Клиент = Врап.СоздатьОбъект(HttpClient);
    Контент = Врап.СоздатьОбъект(MultipartFormDataContent);
    Клиент.BaseAddress =Врап.СоздатьОбъект("System.Uri",uriSources);
	
	
	// Вариант отправки Ключ-Значение
    Значения = Врап.СоздатьОбъект("System.Collections.Generic.Dictionary`2[System.String,System.String]");
 
     Значения.Add("Name", "name");
     Значения.Add("id", "id");
  

                //      content.Add(new FormUrlEncodedContent(values));
                Для каждого КлючЗначение из Значения Цикл

                    Контент.Add(Врап.СоздатьОбъект("System.Net.Http.StringContent",КлючЗначение.Value),КлючЗначение.Key);
				КонецЦикла;
				
				
				// Вариант отправки двоичных данных из массива
				Encoding=Врап.ПолучитьТип("System.Text.Encoding");
				
                СтроковыйКонтент =Врап.СоздатьОбъект("System.Net.Http.ByteArrayContent",Encoding.UTF8.GetBytes("Тестовая строка"));

				ContentDisposition=Врап.СоздатьОбъект("System.Net.Http.Headers.ContentDispositionHeaderValue","form-data");
				ContentDisposition.FileName ="ПростоСтрока";
				ContentDisposition.Name ="attachment";


                СтроковыйКонтент.Headers.ContentDisposition = ContentDisposition;
				СтроковыйКонтент.Headers.ContentType = Врап.СоздатьОбъект("System.Net.Http.Headers.MediaTypeHeaderValue","text/plain");
                Контент.Add(СтроковыйКонтент);

				
				// Вариант отправки двоичных данных из файла
                ИмяФайла ="C:/ТестXML";
			
				ПотокФайла =Врап.ПолучитьТип("System.IO.File").OpenRead(ИмяФайла);
                ФайловыйКонтент =Врап.СоздатьОбъект("System.Net.Http.StreamContent",ПотокФайла);
				ContentDisposition=Врап.СоздатьОбъект("System.Net.Http.Headers.ContentDispositionHeaderValue","form-data");
				ContentDisposition.FileName = Врап.ПолучитьТип("System.IO.Path").GetFileName(ИмяФайла);
				
                ФайловыйКонтент.Headers.ContentDisposition = ContentDisposition;
				ФайловыйКонтент.Headers.ContentType = Врап.СоздатьОбъект("System.Net.Http.Headers.MediaTypeHeaderValue","application/octet-stream");
                Контент.Add(ФайловыйКонтент);

                 // Вариант отправки двоичных данных из файла но более краткий
				 ПотокФайла2 =Врап.ПолучитьТип("System.IO.File").OpenRead(ИмяФайла);
                 ФайловыйКонтент2 =Врап.СоздатьОбъект("System.Net.Http.StreamContent",ПотокФайла2);
				 Контент.Add(ФайловыйКонтент2,"attachment","TestXml");

                requestUri = "api/values/SendFiles";

                Результат = Клиент.PostAsync(requestUri, Контент).Result;
                стр = Результат.Content.ReadAsStringAsync().Result;
				
				Сообщить(стр);
				ЗакрытьРесурс(Клиент);
				ЗакрытьРесурс(Контент);
				ЗакрытьРесурс(ПотокФайла);
// Вот как выглядит отправляемый запрос				
//POST http://localhost:40320/api/values/SendFiles HTTP/1.1
//Content-Type: multipart/form-data; boundary="9f2d525a-7383-46ab-8fc7-419d73486c02"
//Host: localhost:40320
//Content-Length: 811
//Expect: 100-continue
//Connection: Keep-Alive

//--9f2d525a-7383-46ab-8fc7-419d73486c02
//Content-Type: text/plain; charset=utf-8
//Content-Disposition: form-data; name=Name

//name
//--9f2d525a-7383-46ab-8fc7-419d73486c02
//Content-Type: text/plain; charset=utf-8
//Content-Disposition: form-data; name=id

//id
//--9f2d525a-7383-46ab-8fc7-419d73486c02
//Content-Disposition: form-data; filename="=?utf-8?B?0J/RgNC+0YHRgtC+0KHRgtGA0L7QutCw?="; name=attachment
//Content-Type: text/plain

//Тестовая строка
//--9f2d525a-7383-46ab-8fc7-419d73486c02
//Content-Disposition: form-data; filename="=?utf-8?B?0KLQtdGB0YJYTUw=?="
//Content-Type: application/octet-stream

//12345
//--9f2d525a-7383-46ab-8fc7-419d73486c02
//Content-Disposition: form-data; name=attachment; filename=TestXml; filename*=utf-8''TestXml

//12345
//--9f2d525a-7383-46ab-8fc7-419d73486c02--

КонецПроцедуры


Запрос достаточно просто отправить. Вот как это приходится делать на чистом 1С Передача файлов и данных на веб-сервер средствами 1С:Предприятие 8.X методом POST

multipart/form-data

Стоит отметить использование 

handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate);
который позволяет хорошо сжимать HTML странцы. Например
uriSources ="https://msdn.microsoft.com/en-us/library/system.net.decompressionmethods(v=vs.110).aspx";

    handler = врап.СоздатьОбъект(HttpClientHandler);
    handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate) ;
  
 Клиент=Врап.СоздатьОбъект(HttpClient,handler);
Стр=Клиент.GetStringAsync(uriSources).Result;
 

Сжимает трафик в 5 раз.

Content-Length: 17129 упакованной, против 87 624 неупакованной

К сожалению, объем получился большим. Поэтому  продолжение использования HTTPClient и парсинг сайтов выделю в отдельную статью. Так будет проще разбираться.

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Жолтокнижниг 250 10.03.16 19:10 Сейчас в теме
(0) Я не нашел, какие требования к Framework?
2. Serginio 823 10.03.16 22:53 Сейчас в теме
16. Serginio 823 28.08.17 15:31 Сейчас в теме
(1) Ты можешь смотреть IsFaulted в ПриОкончанииВыполнения к которой подключаешься

Выполнитель=Врап.ПолучитьАсинхронныйВыполнитель();
ДобавитьОбработчик Выполнитель.ПриОкончанииВыполненияЗадачи, ПриОкончанииВыполнения;




Процедура ПриОкончанииВыполнения(Задача,ДанныеКЗадаче)

    // Обязательно нужно отлавливать ошибку в 1С
    // Иначе она передается в .Net где обрабатывается там
    Попытка
Так как задача может завершиться с ошибкой
Мы должны проверить, и если ошибка нужно предпринять какие то действия
        Если (Задача.IsFaulted) Тогда  // Ошибка выполнения
3. bonv 1079 07.04.16 09:28 Сейчас в теме
(0) Перед публикацией могли хотя бы отформатировать код (Alt+Shift+F)
4. Serginio 823 07.04.16 12:15 Сейчас в теме
(3) bonv,
Форматировал. Только вот вставка в редактор и редактирование на этом сайте не совсем тривиальная задача
5. Гость 04.07.16 22:19
Спасибо за труды, о великий!
6. Serginio 823 04.07.16 22:28 Сейчас в теме
Спасибо за оценку трудов моих скромных.
7. Serginio 823 25.11.16 12:34 Сейчас в теме
Добавлю удобную объектную надстройку к Retst Api Refit: The automatic type-safe REST library for .NET Core, Xamarin and .NET

Вкратце можно описать интерфейс

public interface IGitHubApi
{
    [Get("/users/{user}")]
    Task<User> GetUser(string user);
}


И использовать

var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");

var octocat = await gitHubApi.GetUser("octocat");
8. Arxxximed 10 23.08.17 12:28 Сейчас в теме
У меня не получилось провести тест асинхронных httpзапросов на сервере. Это работать будет только на клиенте?
Прикрепленные файлы:
9. Serginio 823 23.08.17 19:13 Сейчас в теме
Это работает только на клиенте, так как идет привязка к событиям, а на сервере нужно ждать когда событие придет

Вся беда в том, что на сервере нельзя сделать
ДобавитьОбработчик Выполнитель.ПриОкончанииВыполненияЗадачи, ПриОкончанииВыполнения

И ОбработкаВнешнегоСобытия.
Поэтому асинхронные только на клиенте.
Arxxximed; +1 Ответить
10. Arxxximed 10 27.08.17 02:08 Сейчас в теме
Извините, возможно плохо искал. А как получить изображение через Стр=Клиент.GetStringAsync("GetHeaders").Result; как двоичные данные?
Допустим во втроенном HTTPОтвет Если метод ПолучитьТелоКакДвоичныеДанные

Или есть другой метод получения?

Это в идеале,
Ну или хотябы как записывать
11. Arxxximed 10 27.08.17 11:34 Сейчас в теме
Спасибо, методом проб и ошибок нашел одно из решений которое в вдругой ветке предоставили

UTF8=Врап.ПолучитьТип("System.Text.Encoding").GetEncoding(1251);
Данные=Клиент.GetByteArrayAsync("http://oursite.ru/data/2016/08/14/1237073852/7427903.jpg").Result;
output = UTF8.GetString(Данные);
двДанные  = ПолучитьДвоичныеДанныеИзСтроки(output,КодировкаТекста.ANSI,);
двДанные.Записать("B:\ПробаУдалить\ТестовоеИзображение.jpg"); ///Можно и записать если нужно
12. Arxxximed 10 27.08.17 11:37 Сейчас в теме
Если есть Другие более "правильные" варианты подскажите пожалуйста. Вообще не дотнет разработчик
13. Serginio 823 28.08.17 13:20 Сейчас в теме
Ну в Данные ты получаешь массив байтов.
Просто
File=Врап.ПолучитьТип("System.IO.File");
File.WriteAllBytes("B:\ПробаУдалить\ТестовоеИзображение.jpg",Данные);
14. Arxxximed 10 28.08.17 15:10 Сейчас в теме
Сергей, спасибо за ответ. Только я имел ввиду Как из запроса получить двоичные данные как объект 1С , вот нашел такое решение. Можно конечно попробовать и по другому
15. Arxxximed 10 28.08.17 15:16 Сейчас в теме
Так же все таки интересуют вопрос ошибок. У меня сложилась ситуация, что когда запрос возвращает ошибку 404 возникает исключительная ситуация в .Net.
Т.е. я не могу обработать task через wait() или waitall(). Не знаю как правильно решить данный момент. Пока сделал что жду в цикле возвращение True хотя бы одного из свойств;
Задача.IsCompleted;
Задача.IsCanceled;
Задача.IsFaulted;

Хотя это немного наверное не правильно...
17. Arxxximed 10 28.08.17 16:17 Сейчас в теме
Нет, я тут не пользуюсь Асинхронным выполнителем, посмотрел что для моей задачи это немного "Неудобно". я просто создаю массив заданий. Причем массив как объект 1С. И когда нужно прохожусь по этому массиву.
Все равно процедура ПриОкончанииВыполнения начнет выполнятся только после завершения формирующей процедуры. Насколько я правильно понимаю
18. Serginio 823 28.08.17 19:11 Сейчас в теме
Ну можно по аналогии с https://habrahabr.ru/post/307360/
Вызывать Task.WaitAny(массивЗадач);



ПриОкончанииВыполнения будет вызываться после завершения Задачи.

 Клиент=Врап.СоздатьОбъект(HttpClient);
    Задача=Клиент.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx");
    Выполнитель.Выполнить(задача,ТекущаяДата());

// Вот после этого кода, после завершении Задача
19. Arxxximed 10 29.08.17 12:47 Сейчас в теме
Немного проверил работу асинхронного выполнителя. Немного не вижу в нем смысла.
Дело в том, что если мы в Процедуре А() создаем выполнителю множество задач, то результат задач в процедуре-Обработчике мы сможем получить Только!!! После выполнения всей процедуры А. Кроме случаев Когда 1С сама не вызывает "асинхорнные" процедуры , например Вопрос().

Т.е. По сути я могу получить результаты Работы объектов .NET в конце моей процедуры без вызова Асинхронного выполнителя, при этом объекты .NET Выполняют свою работу параллельно работе 1С, что и требует данная тема.

Единственное что дает Выполнитель - это гарантированное выполнение задачи (task), но существенно ухудшает читаемость кода.

Но на выполнение можно сделать проверку в коде 1С циклом как я писал выше
функция ожидания выполнения


По поводу WaitAny , не проверил, но думаю дело будет обстоять так же: Если задача из массива задач будет выполнена с ошибкой ( например возврват 404) , то будет вызвано исключение .Net , которое в 1С не отловишь

Тема очень хороша, спасибо.
20. Serginio 823 29.08.17 14:46 Сейчас в теме
Ну а ты создавай в Процедуре А только задачи, на это уходит миллисекунды.
А вот время для получения результата уже могут быть секунды.

Нет в данном случае возвращается Task и у него можно проверить IsFaulted
21. mar82 15.07.19 10:50 Сейчас в теме
Извиняюсь за вопрос, но на Win 10 x64 получаю стабильно ошибку "Неверное имя объекта" на первой строке Врап = Новый COMОбъект

Нужно ли что-то особенное сделать для Win x64?

Спасибо
22. Serginio 823 15.07.19 12:26 Сейчас в теме
Оставьте свое сообщение

См. также

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    37241    unichkin    74    

Работа с журналом регистрации. Выходим за границы платформы

Журнал регистрации Бесплатно (free)

Работа с журналом регистрации нестандартными средствами. А также немного про использование платформы .NET в экосистеме 1С.

12.05.2020    5560    YPermitin    24    

Как я собрал для себя высокопроизводительный и бесплатный облачный бекенд для 1С на PosgreSQL + PostgREST

Производительность и оптимизация (HighLoad) WEB Интеграция Мобильная разработка Администрирование веб-серверов v8 Бесплатно (free)

В этой статье я расскажу о проблемах бека для мобильных приложений или другого фронта, который требует производительности, быстрой реакции и отказоустойчивости, и как я решил это благодаря opensource проекту PostgREST и СУБД Postgre SQL 12. Проведу простой тест производительности для сравнения 1С с данным решением. Это может быть полезно всем, кто разрабатывает мобильные приложения либо фронтсайд-приложения для 1С на чем угодно - на мобильной платформе или на нативном языке или на Simple UI. И также обзор новых функций SimpleUI для связи с этим бекендом.

31.03.2020    12546    informa1555    31    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    25576    ids79    26    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    30098    tormozit    100    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    23046    John_d    22    

Последовательности событий. Шпаргалка

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    17605    kuzyara    33    

30 задач. Странных и не очень

Практика программирования v8 Бесплатно (free)

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    16877    YPermitin    72    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

В сложных логических выражениях нередко самому автору спустя какое-то время тяжело разобраться, не говоря уже о других программистах. Предлагаемая методика позволяет повысить наглядность таких выражений путем оформления в виде И-ИЛИ дерева и одновременно выполнять их рефакторинг.

20.09.2012    77860    tormozit    131    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

Практика программирования v8 Бесплатно (free)

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    8274    Sibars    19    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    32547    Yashazz    50    

Самый примитивный HTTP-сервис в мире

WEB v8 Бесплатно (free)

Пошаговый пример создания простейшего HTTP-сервиса, который генерирует HTML-страницу для поиска товара, а также реализует асинхронное получение данных из базы.

12.09.2019    21443    YPermitin    26    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

11.07.2007    48203    tormozit    41    

[Шпаргалка] Программное создание элементов формы

Практика программирования Работа с интерфейсом v8 1cv8.cf Бесплатно (free)

Программное создание практически всех популярных элементов формы.

06.09.2019    48565    rpgshnik    63    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    48485    ids79    54    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    27929    YPermitin    24    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    44638    tormozit    74    

Три костыля. Сказ про фокусы в коде

Практика программирования v8 Бесплатно (free)

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    25336    YPermitin    80    

Отслеживание выполнения фонового задания

Практика программирования Универсальные функции Разработка v8 1cv8.cf Бесплатно (free)

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    31174    ids79    16    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    79844    ids79    49    

Выгрузка документа по условию Промо

Практика программирования Разработка v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    16012    m-rv    2    

Фоновое выполнение кода в 1С - это просто

Практика программирования v8 1cv8.cf Бесплатно (free)

Как легко запускать выполнение в фоне, не прибегая к долгому описанию фоновых процедур.

02.08.2019    34478    avalakh    22    

Разбираемся с параметрами редактирования СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    23314    json    13    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    58314    ids79    11    

Как прикрутить ГУИД к регистру сведений Промо

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 Бесплатно (free)

... и немного теории обмена данными. В частности, разберем боль всех, кто пишет небанальные обмены данными: как набору записей регистра сведений назначить гуид и далее использовать его в обмене для идентификации этого набора.

16.04.2019    20143    m-rv    17    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    35434    ids79    27    

Регистры сведений. За кулисами

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    25866    YPermitin    14    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования Разработка v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    19554    SeiOkami    50    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    30488    m-rv    21    

Создание отчетов с помощью СКД - основные понятия и элементы

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    51761    ids79    25    

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Практика программирования Производительность и оптимизация (HighLoad) v8 v8::Запросы Бесплатно (free)

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    24839    dmurk    145    

Регистры накопления. Структура хранения в базе данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    42474    YPermitin    30    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Вариант решения задач с проведением по типовым регистрам нетиповыми регистраторами. Зачем - чтобы при сравнении конфигурации не обращать внимание на свойства регистров и исключить вероятность допущения горькой оплошности при обновлении информационных баз, заменив типы регистраторов основной конфигурации типами конфигурации поставщика. Для программных продуктов, имеющих в своем составе метаданных документ "Корректировка регистров"("Корректировка записей регистров").

05.12.2017    28205    itriot11    34    

HTML-клиент у конфигурации 1С

WEB v8 Бесплатно (free)

Приветствую. В этой публикации опишу свой опыт создания html-клиента для конфигурации 1С с помощью http-сервисов. HTML-клиент в этом случае - это frontend (html + css+ js), который генерирует и выдает пользователю конфигурация + backend, который тоже реализован в этой же конфигурации.

17.04.2019    18459    Smaylukk    119    

О расширениях замолвите слово...

Практика программирования Разработка v8 Бесплатно (free)

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    35152    ellavs    126    

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Практика программирования v8 Бесплатно (free)

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    27297    ellavs    89    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    76209    Serginio    108    

Трюки с внешними источниками данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    31156    YPermitin    53    

Разработка и сценарное тестирование с Vanessa-ADD. Отчетность Allure. Автоматизация запуска сценариев

Практика программирования Vanessa Automation v8 Россия Бесплатно (free)

Формируем отчетность о результатах выполнения сценариев. Автоматизируем запуск.

26.02.2019    21787    Vladimir Litvinenko    27    

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

Практика программирования БСП (Библиотека стандартных подсистем) Роли и права v8 v8::Права Бесплатно (free)

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    38935    ids79    9    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С Промо

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    34531    ids79    40    

EnterpriseData – часть 2. Процесс выгрузки данных

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Основные этапы выгрузки данных через ED, обработчики событий выгрузки, правила обработки данных, правила конвертации объектов, конвертация свойств первого и второго этапов, процедуры БСП, используемые при выгрузке данных, структура «КомпонентыОбмена».

26.12.2018    26616    ids79    31    

Новый подход к обмену данными EnterpriseData

Практика программирования Обмен через XML v8 v8::УФ Россия Бесплатно (free)

Хочу предложить Вашему вниманию цикл статей, посвященных обмену данными через универсальный формат (EnterpriseData или ED).

14.12.2018    41102    ids79    72    

Использование сборок .NET в 1С 7. и 8.x. Создание внешних Компонент. Промо

Разработка внешних компонент v7.7 v8 1cv8.cf 1cv7.md Абонемент ($m)

Данная разработка создана для использования сборок .Net в 1С через преобразование объектов и классов в COM-объекты, которые можно использовать в 1С. Достигается это путем создания класса, реализующего методы интерфейса IReflect public class AutoWrap: IReflect.

1 стартмани

28.11.2013    82100    235    Serginio    71    

EnterpriseData - пример доработки правил конвертации без использования КД 3.0 в расширении конфигурации

Практика программирования Обмен через XML v8 v8::УФ БП3.0 УТ11 Россия Бесплатно (free)

В статье подробно описан реальный пример доработки обмена данными через EnterpriseData (универсальный формат обмена) между конфигурациями УТ 11.4 и Бухгалтерия 3.0

16.11.2018    36768    ids79    42    

Программное заполнение пользовательских параметров и отборов СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Публикация представляет из себя краткие примеры того, как можно заполнять параметры СКД программно так, чтобы все параметры и отборы были доступны в быстрых настройках и в обычных (типовых) настройках параметров и отборов СКД.

13.11.2018    46902    Unk92    25    

Создание телеграм бота с гугл авторизацией, обратными вызовами и уведомлениями об обновлении через сервер-маршрутизатор

WEB v8 1cv8.cf Бесплатно (free)

Статья детально рассказывает обо всех аспектах настройки телеграм бота, работающего через сервер-маршрутизатор посредством обратных вызовов. Приведены примеры работы отправки/исправления сообщений, отправки файлов, работы с внутренними и встроенными запросами. Создание клавиатуры. Авторизация пользователей через gmail.

07.11.2018    31185    🅵🅾️🆇    60    

Тестер: частые вопросы Промо

Практика программирования v8 Бесплатно (free)

Ошибкам бой - тесты норма жизни!

25.07.2018    29175    grumagargler    28