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

09.03.16

Разработка - Запросы

Очень часто нужно при работе с 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 и парсинг сайтов выделю в отдельную статью. Так будет проще разбираться.

.Net HTTPClient multipart/form-data C#

См. также

Микро консоль для запросов к MySQL базе из 1С: Предприятие 7.7

Инструментарий разработчика Запросы Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Обработка, позволяющая выполнять запросы к базе, лежащей в MySQL, для 1С:Предприятие 7.7.

10.08.2022    2932    6    crocolo    0    

2

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

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

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

12.05.2020    18392    Infostart    32    

91

Универсальный способ сравнения таблиц

Универсальные функции Запросы Платформа 1С v7.7 Платформа 1С v8.3 Бесплатно (free)

На эту тему уже есть статьи, но этот способ нигде не описан. Хотя я его использую с тех пор, как занимаюсь программированием. Его преимущество в простоте и универсальности: можно применять на 1С, SQL, а также в любом другом языке программирования.

05.07.2015    21621    json    3    

22

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

Запросы Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Пример получения остатков по складу по запросу по почте из программы 1С 7.7. Для получения остатков необходимо пользователю с любого почтовика (с любого "мыла") отправить текст сообщения GiveMyStockBalance_ForAnalize на почтовый адрес определенный в Константа.СерверПолучения. Программа выдаст остатки (можно переписать функцию для выдачи любых данных) в формате xls на почту указанную в константе Константа.СерверОтправки. Программа может быть полезна в тех организациях где трудно или невозможно осуществить прямой доступ к 1С сотрудников для просмотра необходимых данных. Также можно организовать некий почтамт - запрос для клиентов - при посылке определенного логина клиентом на его почту будет автоматически выслана информация, например, акт сверки с клиентов, или процент выполнения его заказа и т.д.

3 стартмани

25.03.2014    25143    5    protexprotex    3    

5

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

Разработка внешних компонент Платформа 1С v7.7 Платформа 1С v8.3 Конфигурации 1cv8 Конфигурации 1cv7 Абонемент ($m)

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

1 стартмани

28.11.2013    108367    334    Serginio    80    

141

Реализация условий в прямых запросах к журналу расчета.

Зарплата Запросы Расчет 7.7 1С:Зарплата и кадры 7.7 Абонемент ($m)

Обзор методов реализации условий и функций с условиями в обращениях к журналу расчетов при помощи прямого запроса.

1 стартмани

06.12.2012    14082    nicotin    5    

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

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




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

    // Обязательно нужно отлавливать ошибку в 1С
    // Иначе она передается в .Net где обрабатывается там
    Попытка
Так как задача может завершиться с ошибкой
Мы должны проверить, и если ошибка нужно предпринять какие то действия
        Если (Задача.IsFaulted) Тогда  // Ошибка выполнения
3. bonv 1508 07.04.16 09:28 Сейчас в теме
(0) Перед публикацией могли хотя бы отформатировать код (Alt+Shift+F)
It-developer; +1 Ответить
4. Serginio 938 07.04.16 12:15 Сейчас в теме
(3) bonv,
Форматировал. Только вот вставка в редактор и редактирование на этом сайте не совсем тривиальная задача
5. Гость 04.07.16 22:19
Спасибо за труды, о великий!
6. Serginio 938 04.07.16 22:28 Сейчас в теме
Спасибо за оценку трудов моих скромных.
7. Serginio 938 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 34 23.08.17 12:28 Сейчас в теме
У меня не получилось провести тест асинхронных httpзапросов на сервере. Это работать будет только на клиенте?
Прикрепленные файлы:
9. Serginio 938 23.08.17 19:13 Сейчас в теме
Это работает только на клиенте, так как идет привязка к событиям, а на сервере нужно ждать когда событие придет

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

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

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

Это в идеале,
Ну или хотябы как записывать
11. Arxxximed 34 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 34 27.08.17 11:37 Сейчас в теме
Если есть Другие более "правильные" варианты подскажите пожалуйста. Вообще не дотнет разработчик
13. Serginio 938 28.08.17 13:20 Сейчас в теме
Ну в Данные ты получаешь массив байтов.
Просто
File=Врап.ПолучитьТип("System.IO.File");
File.WriteAllBytes("B:\ПробаУдалить\ТестовоеИзображение.jpg",Данные);
14. Arxxximed 34 28.08.17 15:10 Сейчас в теме
Сергей, спасибо за ответ. Только я имел ввиду Как из запроса получить двоичные данные как объект 1С , вот нашел такое решение. Можно конечно попробовать и по другому
15. Arxxximed 34 28.08.17 15:16 Сейчас в теме
Так же все таки интересуют вопрос ошибок. У меня сложилась ситуация, что когда запрос возвращает ошибку 404 возникает исключительная ситуация в .Net.
Т.е. я не могу обработать task через wait() или waitall(). Не знаю как правильно решить данный момент. Пока сделал что жду в цикле возвращение True хотя бы одного из свойств;
Задача.IsCompleted;
Задача.IsCanceled;
Задача.IsFaulted;

Хотя это немного наверное не правильно...
17. Arxxximed 34 28.08.17 16:17 Сейчас в теме
Нет, я тут не пользуюсь Асинхронным выполнителем, посмотрел что для моей задачи это немного "Неудобно". я просто создаю массив заданий. Причем массив как объект 1С. И когда нужно прохожусь по этому массиву.
Все равно процедура ПриОкончанииВыполнения начнет выполнятся только после завершения формирующей процедуры. Насколько я правильно понимаю
18. Serginio 938 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 34 29.08.17 12:47 Сейчас в теме
Немного проверил работу асинхронного выполнителя. Немного не вижу в нем смысла.
Дело в том, что если мы в Процедуре А() создаем выполнителю множество задач, то результат задач в процедуре-Обработчике мы сможем получить Только!!! После выполнения всей процедуры А. Кроме случаев Когда 1С сама не вызывает "асинхорнные" процедуры , например Вопрос().

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

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

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


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

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

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

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

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