Евгений Колесников 4 lat temu
rodzic
commit
41134a5a31
2 zmienionych plików z 140 dodań i 15 usunięć
  1. 99 13
      articles/cs_http.md
  2. 41 2
      readme.md

+ 99 - 13
articles/cs_http.md

@@ -1,4 +1,4 @@
-# Получение списка материалов выбранного продукта
+# HTTP запросы в C#. Получение списка материалов выбранного продукта
 
 Возвращаемся к проекту на C#.
 
@@ -26,7 +26,7 @@ Authorization: Basic esmirnov 111103
 var client = new HttpClient();
 ```
 
-В АПИ мы использовали "базовую" авторизацию. В C# я не нашёл встроенных библиотек для облегчения формирования заголовка для "базовой" авторизации (вероятно они есть в сборке для веб разработки, но мы должны пользоваться только тем, что есть в обычной)
+В АПИ мы использовали "базовую" авторизацию. В C# я не нашёл встроенных библиотек для облегчения формирования заголовка для "базовой" авторизации
 
 Формируем base64-кодированную строку:
 
@@ -55,20 +55,13 @@ private string GetString(string url){
 
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", basic);
 
-    // тут самое интересное - клиент возвращает не строку, а "задачу", которая по выполнении вернёт строку
-    Task<string> task = client.GetStringAsync(url);
-
-    // методом Wait мы превращаем нашу функцию в синхронную
-    task.Wait();
-
-    // и возвращаем результат ВЫПОЛНЕННОЙ задачи
-    return task.Result;
+    return client.GetStringAsync(url).Result;
 }
 ```
 
 ## Разбор JSON
 
-Теперь допишем интерфейс нашего поставщика данных:
+Сначала допишем интерфейс нашего поставщика данных:
 
 ```cs
 interface IDataProvider
@@ -78,7 +71,9 @@ interface IDataProvider
 }    
 ```
 
-Здесь я класс назвал не **Material**, а **MaterialTC**, потому что АПИ возвращает не весь объект материал, а только название и количество (**T**itle**C**ount).
+Здесь я класс назвал не **Material**, а **MaterialTC**, потому что АПИ возвращает не весь объект Material, а только название и количество (**T**itle**C**ount).
+
+### Классический вариант
 
 И реализуем его:
 
@@ -118,13 +113,104 @@ public IEnumerable<MaterialTC> GetMaterials(int ProductId) {
     using (var sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(resp))))
     {
         var answer = (Answer)Serializer.ReadObject(sr.BaseStream);
-
         foreach (MaterialTC material in answer.notice.data)
         {
             result.Add(material);
         }
     }
+    return result;
+}
+```
+
+### Вариант с регулярками
 
+Стандартный вариант слишком монстрообразный, на мой взгляд. Можно тоже самое реализовать через регулярки:
+
+Класса нам достаточно одного:
+
+```cs
+internal class MaterialTC
+{
+    public string Title { get; set; }
+    public int Count { get; set; }
+}
+```
+
+Реализация метода **GetMaterials**:
+
+```cs
+public IEnumerable<MaterialTC> GetMaterials(int ProductId) {
+    var result = new List<MaterialTC>();
+
+    var resp = GetString($"http://localhost:8080/Material?product_id={ProductId}");
+
+    Regex regex = new Regex(@"\{""Title"":""(.*?)"",""Count"":(.*?)\}", RegexOptions.Singleline);
+    MatchCollection matches = regex.Matches(resp);
+    if (matches.Count > 0)
+    {
+        foreach (Match match in matches)
+            res.Add(new MaterialTC { 
+                Title = match.Groups[1].ToString(), 
+                Count=Convert.ToInt32(match.Groups[2].ToString()) 
+            });
+    }
     return result;
 }
+```
+
+Надо, конечно, ещё проверить валидность ответа (notice->data|notice->answer), но с регулярками это тоже проще - вообще не нужно рисовать новый класс.
+
+### Вариант с JavaScriptSerializer
+
+Оказывается на **WorldSkills** можно использовать не только "голый" **.NET Framework**, но и библиотеки из других компонентов **Visual Studio**.
+
+В пространстве имён **System.Web.Script.Serialization** есть класс **JavaScriptSerializer**, который выглядит попроще чем классическая реализация:
+
+```cs
+// целевые классы нам по прежнему нужны, но уже без всяких аннотаций
+internal class MaterialTC
+{
+    public string Title { get; set; }
+    public int Count { get; set; }
+}
+
+internal class Notice
+{
+    public Material[] data;
+}
+
+internal class Answer
+{
+    public Notice notice;
+}
+
+
+// в месте, где нам нужно распарсить JSON создаем сериализатор и разбираем строку
+var serializer = new JavaScriptSerializer();
+var answer = serializer.Deserialize<Answer>("тут ваша JSON-строка");
+
+// и ВСЁ
+```
+
+## POST запросы с JSON
+
+Возможно понадобится что-то послать в АПИ, разберём как это делается:
+
+```cs
+// сначала запихиваем объект в JSON-строку. 
+
+// тут можно завести отдельный класс, а можно создать анонимный объект
+var obj = new {username="qq", password="ww"};
+
+// и тем же сериализатором превращаем в JSON-строку
+var jsonString = serializer.Serialize(obj);
+
+// создаём контент для запроса
+var json = new StringContent(jsonString, Encoding.UTF8, "application/json");
+
+// и вызываем POST-запрос
+var client = new HttpClient();
+var result = client.PostAsync("http://localhost:8080/echo", json).Result;
+
+Console.WriteLine(result.Content.ReadAsStringAsync().Result);
 ```

+ 41 - 2
readme.md

@@ -150,21 +150,60 @@ http://sergeyteplyakov.blogspot.com/2014/01/microsoft-fakes-state-verification.h
 
 10. [ViewPager, Fragments, Tabs](./articles/pager.md)
 
+<!-- 
+
+TODO
+
+BottomNavigation + frames
+figma
+api (swagger)
+http (получать контент при ошибке)
+структурировать по экранам
+темы DayNight
+хранение состояния (preferences)
+ViewPager
+multipart/form-data - загрузка картинок на сервер
+источник фото - камера/галерея
+swype to delete
+swype вниз (обновление списка)
+tablayout
+
+kerio
+
+-->
+
 ## Тема 5.1.5. Разработка своего API.
 
 1. [API. PHP-сервер. GET-запрос.](./articles/api_php.md)
 
 ## Тема 5.1.6. C#, разбор задания.
 
-1. [Сессия 1. Создание БД. Импорт данных. Окно авторизации](./articles/wsr_1.md)
+<!-- 1. [Сессия 1. Создание БД. Импорт данных. Окно авторизации](./articles/wsr_1.md) -->
+1. [HTTP запросы в C#. Получение списка материалов выбранного продукта](./articles/cs_http.md)
+
+<!-- 
+
+Создание базы данных
+Импорт данных
+Авторизация, главное окно
+Форма ввода данных, список с фильтрацией, поиском и сортировкой
+HTTP-запросы, разбор JSON, XML
+Разработка АПИ (php-сервер)
+Мобильное приложение
+ER-диаграмма
+Проектирование (Use-case, UML)
+Формирование отчетов (PDF)
+Формирование графиков
+Тестирование
+Библиотека классов
 
+-->
 
 ## Документация
 
 1. [Руководство пользователя](./articles/user_manual.md)
 
 <!-- 
-1. [Получение списка материалов выбранного продукта](./articles/cs_http.md)
 
 
 кнопки с картинками (нижнее или боковое меню)(фрагменты)