Парсер курсів валют українських банків, створений на основі Windows Service
Зміст
.Вступ
.
Опис предметної галузі застосування програмного забезпечення, що було
розроблене в ході курсової роботи
.
Опис специфічних просторів імен, класів, функцій, що були використані при
роботі з системними процесами
4.Табличний опис класів (клас
<https://msdn.microsoft.com/ru-ru/library/System.Windows.Forms.ComboBox(v=vs.110).aspx>,
конструктор(и),
<https://msdn.microsoft.com/ru-ru/library/system.windows.forms.combobox.combobox(v=vs.110).aspx>методи,
<https://msdn.microsoft.com/ru-ru/library/system.windows.forms.combobox_methods(v=vs.110).aspx>властивості,
події)
. Демонстрація інтерфейсу ПЗ (програмного
забезпечення)
. Програмний код
Висновки
Перелік посилань
1.Вступ
Робота з грошима, фінансовими
обертами, в банківських структурах чи на держпідприємствах або ж інших
підприємствах, де мова йде не тільки про нашу валюту, а й про такі як
долар,євро чи рубль має безпосереднє відношення до курсу, при чому до його
різких змін. В цьому і проявляється одна з найбільших переваг проекту - швидка
реакція на зміни в курсах.
В товарно-грошових відносинах між
державами дана інформація також є дуже важливою, оскільки ціна продукту, що йде
експортується майже вказана в міжнародних валютах, таких як долар чи євро. А не
маючи інформації щодо обміну валют можна понести великі збитки, купляючи чи
продаючи певну продукцію.
Завданням курсової роботи було
створення Windows service та клієнта-програми до неї, що виводить діючі курси
валют (купівлі\продажу долара,євро та рубля) деяких українських банків в режимі
онлайн.
Додатковим завданням було створення
Windows служби, яка саме і виконує операцію парсингу та через контракт передає
інформацію до клієнту. Для правильної роботи треба налаштувати дану службу та
зробити установку її на комп'ютер. Після цього її треба запустити та переходити
до використання. Можна налаштувати службу, щоб вона починала працювати зі
стартом системи та неперервно виконувала свої функції. Це полегшує роботу в
деяких випадках.
service програма валюта
онлайн
2. Опис предметної галузі застосування
програмного забезпечення, що було розроблене в ході курсової роботи
Тематика проекту курсової роботи
тісно пов’язана із грошовими операціями, при чому будь-де: чи то в банківській
сфері, чи то в сфері купівлі продажу тощо.
Відносини між країнами завжди
пов’язані на розподілі, обміні чи продажу. А всі ці сфери базуються на грошових
обертах, причому у іноземних валютах, частіш за все. Наприклад, якщо брати нашу
країну, то імпортований товар з інших країн купується, частіш за все, за такі
валюти як долар чи євро, які в свою чергу мають постійно змінний курс до
гривні. І це стосується не тільки експорту чи імпорту, але й економічних,
та,навіть, політичних відносин.
В банківській сфері дана програма
використовується на постійній основі, оскільки велика частина операцій в банку
пов’язана із обміном валют,який має тенденцію до змін. Завдяки інформаторам
курсів валют люди роблять висновки та роблять прогнози щодо купівлі чи продажу
своїх збережень в банку.
Також актуальною функція даного
проекту є для загальнодержавних питань. Країни, що не мають потрібної кількості
ресурсів змушені купувати їх у інших країн, зазвичай за міжнародну валюту-долар
чи євро. Від цього залежить рівень інфляції в країні, ціни не тільки на ці
ресурси,але й на всі, продукти, виготовлення яких пов’язане з цими ресурсами.
Наприклад ціна на нафту прямо пропорційно впливає на ціну хліба або інших
продуктів, для збирання або вирощування яких потрібне пальне.
Аналогічні програми виконують ту ж
функцію, але їх об’єктом є не курси валют, а світові акції, чи індекси акцій
тощо. За принципом роботи проекту можна виводити будь-які дані та записувати їх
у таблицю. Схожими за принципом є також інформатори погоди,які виводять погоду
у вигляді чисел,які позначають температуру,силу вітру і т.д.
Серед недоліків можна виділити лише:
залежність від доступу до мережі Internet та обмеження у кількості інформації,
що виводиться, оскільки при збільшенні кількості - зменшується швидкість
обробки даних.
. Опис специфічних просторів імен,
класів, функцій, що були використані при роботі з системними процесами.
Простори імен:HtmlAgilityPack цей
простір імен має 20 основних класів, які дають можливість парсити
Web-сторінку(витягувати курси валют з нашого xml файлу). Назви методів цієї
бібліотеки відповідають інтерфейсам DOM. Html перетворюється на xml , але для
роботи доступні такі можливості: Linq to Objects,XPATH,XSLT.
Простір імен
System.Runtime.Serialization складється з класів,які дозволяють виконувати
серіалізацію та десеріалізацію об’єктів(процес перетворення об’єкта в лінійну
послідовність для збереження або передачі на інший комп’ютер або отримання
збережених даних та відновлення з них об’єкту).System.ServiceModel представляє
нам класи, що пов’язані з моделлю служби Windows
Простір імен System.Collections.Generic
містить класи та інтерфейси, що визначають універсальні колекції,які дозволяють
створювати строго типізовані колекції(це забезпечує високу продуктивність та
безпеку типів)System.IO містить типи, дозволяючі здійснювати читання та запис в
файли та потоки даних, а також типи для базової підтримки файлів та
папок.System.Net представляє загальні методи обміну даними з ресурсом, заданим
URI.System.Linq містить класи та інтерфейси,що підтримують запити, що
використовують LINQ.
Функції:
) public List<Bank> ParseThePages(List<string>
urls)
/*функція, використовуючи url
адреси, виконує парсинг даних, що знаходяться на даних сторінках
) private static Bank
GetBank(HtmlDocument doc)
/*функція створює нову строчку,
обирає таблицю та вибирає з неї назву банку, перетворює його на об’єкт
) private static string
GetHtml(string url
/* функція отримання html сторінки
через запит HttpWebRequest request та перевід сторінки в формат строчки
4.Табличний опис класів (клас
<https://msdn.microsoft.com/ru-ru/library/System.Windows.Forms.ComboBox(v=vs.110).aspx>,
конструктор(и),
<https://msdn.microsoft.com/ru-ru/library/system.windows.forms.combobox.combobox(v=vs.110).aspx>методи,
<https://msdn.microsoft.com/ru-ru/library/system.windows.forms.combobox_methods(v=vs.110).aspx>властивості,
події)
1)public class ParsingService
|
Конструктор
|
стандартний
|
Методи: 4 методи(1 відкритий та 3 приватні)
:
|
1.public List<Bank>
ParseThePages(List<string> urls) Функція парсингу вказаних сторінок за
url 2.private static Bank ParseTheCurrentPage(string url) Функція парсингу
однієї сторінки за url 3.private static Bank GetBank(HtmlDocument doc)
Функція отримання об’єкту банка за вказаним html документом 4.private static
string GetHtml(string url); Функція для отримання html сторінки
|
Властивості:
|
немає
|
Події:
|
немає
|
2)public class Bank
|
Конструктор
|
стандартний
|
Методи:
|
немає
|
Властивості:
|
1.public string Name { get; set; } 2.public
string UsdBuy { get; set; } 3.public string UsdSale { get; set; } 4.public
string EurBuy { get; set; } 5.public string EurSale { get; set; } 6.public
string RubBuy { get; set; } 7.public string RubSale { get; set; }
|
Події:
|
немає
|
3)public partial class FormMain : Form
|
Конструктор:
|
визивається стандартна функція ініціалізації
компонентів форми та ініціалізується змінна _client
|
Методи:
|
private void
FillTheDataGridView(List<Bank> banks)
private void btn_Parse_Click(object sender,
EventArgs e) public FormMain() private List<string> _bankUrls = new
List<string>()
|
Властивості
|
немає
|
Події:
|
немає
|
Події:
|
немає
|
4) public partial class MyParsingService :
ServiceBase
|
Конструктор:
|
одна приватна функція ініціалізації та 2
невизначених функції;
|
Методи:
|
protected override void OnStop() protected
override void OnStart(string[] args)
|
Властивості:
|
немає
|
немає
|
Події:
|
немає
|
. Демонстрація інтерфейсу ПЗ
(програмного забезпечення)
Мал.1 Робоче вікно програми
Програма має небагато елементів,
серед них:
) Button btn_Parse, що викликає
функцію парсингу
) DataGridView dgv_ExchangeRate, я
вку записуються дані щодо курсів валют
) DataGridViewTextBoxColumn bankName
- назва банку
) DataGridViewTextBoxColumn
usdBuy(колонка) - купівля долару
) DataGridViewTextBoxColumn
usdSale(колонка) - продаж долару
) DataGridViewTextBoxColumn
eurBuy(колонка) - купівля євро
) DataGridViewTextBoxColumn
eurSale(колонка) - продаж євро
) DataGridViewTextBoxColumn
rubBuy(колонка) - купівля рубля
) DataGridViewTextBoxColumn
rubSale(колонка) - продаж рубля
Мал.2 Вікно,заповнене даними
)Для відображення даних потрібен
прямий доступ до мережі Інтернет;
)Розмір вікна програми можна
змінювати;
)Розмір колонок та рядків також
можна довільно змінювати;
.Програмний код
.csSystem;System.Collections.Generic;System.Linq;System.Runtime.Serialization;System.ServiceModel;System.Text;ParsingService
{
// NOTE: You can use the
"Rename" command on the "Refactor" menu to change the
interface name "IParsingService" in both code and config file
together.
[ServiceContract]interface
IParsingService
{
[OperationContract]<Bank>
ParseThePages(List<string> urls);
}
}.csSystem;System.Collections.Generic;System.Linq;System.Runtime.Serialization;System.ServiceModel;System.Text;HtmlAgilityPack;System.Net;System.IO;ParsingService
{
// NOTE: You can use the "Rename"
command on the "Refactor" menu to change the class name
"ParsingService" in both code and config file together.class
ParsingService : IParsingService
{
//функция парсинга указаных страниц
по их url адресахList<Bank> ParseThePages(List<string> urls)
{<Bank> lstOfBanks = new
List<Bank>();(var bankUrl in urls)
{.Add(ParseTheCurrentPage(bankUrl));
}lstOfBanks;
}
//функция парсинга одной страницы по
ее url адресуstatic Bank ParseTheCurrentPage(string url)
{html = GetHtml(url);doc = new
HtmlDocument();.LoadHtml(html);GetBank(doc);
}
//функция получения обьекта Банка по
указаному HTML документуstatic Bank GetBank(HtmlDocument doc)
{
//информация о валюте в формате
строкиinfo = "";
//информация о валюте ы формате
масива строк[] kursInfo = new string[7];
//получение нужной нам таблицы с
HTML страницыtable = doc.DocumentNode.SelectNodes("//table")[0];
//получаем имя банка=
doc.DocumentNode.SelectNodes("//title")[0].InnerText.Substring(11);=
info.Replace(" ", ";");
//перебираем все валюты в
таблице(var tr_element in table.ChildNodes)
{(tr_element.Name == "tr")
{
//Проверка на соответствие тега
<td>(tr_element.ChildNodes[1].Name == "td")
{
//добавляем инфомацмию о покупке
валюты+= tr_element.ChildNodes[3].FirstChild.InnerText + ";";
//добавляем инфомацмию о продаже
валюты+= tr_element.ChildNodes[5].FirstChild.InnerText + ";";
}
}
}
//разбиваем строку с информацией о
банке в масив строк для удобного создания обьекта Банка(info != "")=
info.Split(';');
//возращаем обьект Банкаnew Bank()
{= kursInfo[0],= kursInfo[1],=
kursInfo[2],= kursInfo[3],= kursInfo[4],= kursInfo[5],= kursInfo[6]
};
}
//Функция для получения HTML
страницыstatic string GetHtml(string url)
{
//Делаем запрос по указаному
urlrequest = HttpWebRequest.Create(url) as HttpWebRequest;
//Получаем ответ по запросуresponce
= request.GetResponse() as HttpWebResponse;
//Считываем ответ и переводим его в
string форматsr = new StreamReader(responce.GetResponseStream(),
Encoding.Default);html = sr.ReadToEnd();.Close();html;
}
}
{class Bank
{string Name { get; set; }string
UsdBuy { get; set; }string UsdSale { get; set; }string EurBuy { get; set;
}string EurSale { get; set; }string RubBuy { get; set; }string RubSale { get;
set; }
}
}.config
<?xml version="1.0"
encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime
version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<system.serviceModel>
<services>
<service
name="ParsingService.ParsingService"
behaviorConfiguration="mexBehavior">
<endpoint
address="ParsingService" binding="basicHttpBinding"
contract="ParsingService.IParsingService"></endpoint>
<endpoint
address="ParsingService" binding="netTcpBinding"
contract="ParsingService.IParsingService"></endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add
baseAddress="http://localhost:9001/ParsingService"/>
<add
baseAddress="net.tcp://localhost:9002/ParsingService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior
name="mexBehavior">
<serviceMetadata
httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>.csSystem;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Threading.Tasks;System.Windows.Forms;ParserClient.ParserService;ParserClient
{partial class FormMain : Form
{_client;List<string>
_bankUrls = new List<string>()
{
"http://finance.i.ua/bank/73/",
"http://finance.i.ua/bank/29/",
"http://finance.i.ua/bank/2/",
"http://finance.i.ua/bank/79/",
"http://finance.i.ua/bank/26/",
"http://finance.i.ua/bank/9/",
"http://finance.i.ua/bank/8/",
"http://finance.i.ua/bank/4/",
"http://finance.i.ua/bank/23/",
"http://finance.i.ua/bank/13/",
"http://finance.i.ua/bank/12/",
"http://finance.i.ua/bank/30/",
"http://finance.i.ua/bank/52/"
};FormMain()
{();
_client = new
ParsingServiceClient("BasicHttpBinding_IParsingService");
}void btn_Parse_Click(object sender,
EventArgs e)
{
//парсим указаный масив url адресов
и получаем масив банков.конвертировали в список<Bank> banks =
_client.ParseThePages(_bankUrls.ToArray<string>()).ToList<Bank>();
//вычесляем количество строк
таблицы_ExchangeRate.RowCount = banks.Count;
//заполняем таблицу информацией о
банках(banks);
}void
FillTheDataGridView(List<Bank> banks)
{(int i = 0; i <
dgv_ExchangeRate.RowCount; i++)
{_ExchangeRate[0, i].Value =
banks[i].Name;_ExchangeRate[1, i].Value = banks[i].UsdBuy;_ExchangeRate[2,
i].Value = banks[i].UsdSale;_ExchangeRate[3, i].Value =
banks[i].EurBuy;_ExchangeRate[4, i].Value = banks[i].EurSale;_ExchangeRate[5,
i].Value = banks[i].RubBuy;_ExchangeRate[6, i].Value = banks[i].RubSale;
}
}
}
}.csSystem;System.Collections.Generic;System.ComponentModel;System.Data;System.Diagnostics;System.Linq;System.ServiceModel;System.ServiceModel.Description;System.ServiceProcess;System.Text;System.Threading.Tasks;WinParsingService
{partial class MyParsingService :
ServiceBase
{ServiceHost _host = null;
MyParsingService()
{();
}override void OnStart(string[]
args)
{(_host != null)
_host.Close();
_host = new
ServiceHost(typeof(ParsingService.ParsingService));
}
override void OnStop()
{(_host != null)
{
_host.Close();
_host = null;
}
}
}
}.Designer.csWinParsingService
{class MyParsingService
{
/// <summary>
/// Required designer variable.
///
</summary>System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being
used.
/// </summary>
/// <param
name="disposing">true if managed resources should be disposed;
otherwise, false.</param>override void Dispose(bool disposing)
{(disposing && (components
!= null))
{.Dispose();
}.Dispose(disposing);
}
#region Component Designer generated
code
/// <summary>
/// Required method for Designer
support - do not modify
/// the contents of this method with
the code editor.
/// </summary>void
InitializeComponent()
{= new System.ComponentModel.Container();.ServiceName
= "ParsingService";
}
#endregion
}
}ParserClient
{class FormMain
{
/// <summary>
/// Required designer variable.
///
</summary>System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being
used.
/// </summary>
/// <param
name="disposing">true if managed resources should be disposed;
otherwise, false.</param>override void Dispose(bool disposing)
{(disposing && (components
!= null))
{.Dispose();
}.Dispose(disposing);
}
#region Windows Form Designer
generated code
/// <summary>
/// Required method for Designer
support - do not modify
/// the contents of this method with
the code editor.
/// </summary>void
InitializeComponent()
{.ComponentModel.ComponentResourceManager
resources = new
System.ComponentModel.ComponentResourceManager(typeof(FormMain));.btn_Parse =
new System.Windows.Forms.Button();.dgv_ExchangeRate = new
System.Windows.Forms.DataGridView();.bankName = new
System.Windows.Forms.DataGridViewTextBoxColumn();.usdBuy = new
System.Windows.Forms.DataGridViewTextBoxColumn();.usdSale = new
System.Windows.Forms.DataGridViewTextBoxColumn();.eurBuy = new
System.Windows.Forms.DataGridViewTextBoxColumn();.eurSale = new
System.Windows.Forms.DataGridViewTextBoxColumn();.rubBuy = new
System.Windows.Forms.DataGridViewTextBoxColumn();.rubSale = new
System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dgv_ExchangeRate)).BeginInit();.SuspendLayout();
//
// btn_Parse
// .btn_Parse.Location = new
System.Drawing.Point(658, 12);.btn_Parse.Name =
"btn_Parse";.btn_Parse.Size = new System.Drawing.Size(101,
36);.btn_Parse.TabIndex = 0;.btn_Parse.Text = "Вывести курсы
валют";.btn_Parse.UseVisualStyleBackColor = true;.btn_Parse.Click += new
System.EventHandler(this.btn_Parse_Click);
//
// dgv_ExchangeRate
//
.dgv_ExchangeRate.AllowUserToAddRows =
false;.dgv_ExchangeRate.AllowUserToDeleteRows =
false;.dgv_ExchangeRate.ColumnHeadersHeightSizeMode =
System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;.dgv_ExchangeRate.Columns.AddRange(new
System.Windows.Forms.DataGridViewColumn[]
{.bankName,.usdBuy,.usdSale,.eurBuy,.eurSale,.rubBuy,.rubSale});.dgv_ExchangeRate.Location
= new System.Drawing.Point(12, 12);.dgv_ExchangeRate.Name = "dgv_ExchangeRate";.dgv_ExchangeRate.ReadOnly
= true;.dgv_ExchangeRate.RowHeadersVisible = false;.dgv_ExchangeRate.Size = new
System.Drawing.Size(623, 322);.dgv_ExchangeRate.TabIndex = 1;
//
// bankName
// .bankName.HeaderText =
"Банк";.bankName.Name = "bankName";.bankName.ReadOnly =
true;.bankName.Width = 200;
//
// usdBuy
// .usdBuy.HeaderText = "USD
Покупка";.usdBuy.Name = "usdBuy";.usdBuy.ReadOnly =
true;.usdBuy.Width = 70;
//
// usdSale
// .usdSale.HeaderText = "USD
Продажа";.usdSale.Name = "usdSale";.usdSale.ReadOnly =
true;.usdSale.Width = 70;
//
// eurBuy
//
// eurSale
// .eurSale.HeaderText = "EUR
Продажа";.eurSale.Name = "eurSale";.eurSale.ReadOnly =
true;.eurSale.Width = 70;
//
// rubBuy
// .rubBuy.HeaderText = "RUB
Покупка";.rubBuy.Name = "rubBuy";.rubBuy.ReadOnly =
true;.rubBuy.Width = 70;
//
// rubSale
// .rubSale.HeaderText = "RUB
Продажа";.rubSale.Name = "rubSale";.rubSale.ReadOnly =
true;.rubSale.Width = 70;
//
// FormMain
// .AutoScaleDimensions = new
System.Drawing.SizeF(6F, 13F);.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Font;.ClientSize = new
System.Drawing.Size(774, 362);.Controls.Add(this.dgv_ExchangeRate);.Controls.Add(this.btn_Parse);.Icon
=
((System.Drawing.Icon)(resources.GetObject("$this.Icon")));.MaximumSize
= new System.Drawing.Size(790, 1000);.MinimumSize = new
System.Drawing.Size(790, 400);.Name = "FormMain";.Text = "Курсы
валют";
((System.ComponentModel.ISupportInitialize)(this.dgv_ExchangeRate)).EndInit();.ResumeLayout(false);
}
#endregionSystem.Windows.Forms.Button
btn_Parse;System.Windows.Forms.DataGridView
dgv_ExchangeRate;System.Windows.Forms.DataGridViewTextBoxColumn
bankName;System.Windows.Forms.DataGridViewTextBoxColumn
usdBuy;System.Windows.Forms.DataGridViewTextBoxColumn
usdSale;System.Windows.Forms.DataGridViewTextBoxColumn
eurBuy;System.Windows.Forms.DataGridViewTextBoxColumn
eurSale;System.Windows.Forms.DataGridViewTextBoxColumn rubBuy;System.Windows.Forms.DataGridViewTextBoxColumn
rubSale;
}
}
Висновки
Програма виконувалась на трьох
етапах:
)створення сервіса-служби
)створення хоста, на якому була
реалізована програма
)створення додатку, за допомогою
якого ми можемо бачити результат роботи програми вцілому
Принцип роботи програми такий, що
запускаючи наш клієнт ми через контракт звертаємося до сервісу, що виконує
роботи парсингу та через клавішу в нашому інтерфейсі виводимо результат на
екран.
Конфігурації були автоматично
налаштовані та встановлені як App.config за допомогою функції mexBehaviour.
Основні елементи:в програмі є
об'єктом с даними
Ми отримали масив банків із масиву
url-адрес і конвертували його у списокinfo - це змінна з інформацією, що
використовувалась- таблиця, в якій демонструвався результат
В IParsingService я створив
інтерфейс(контракт) програми, а в ParsingService - реалізацію інтерфейсу.
Дана програма може бути корисною у
багатьох напрямках діяльності, в особливості банківській. У даній сфері можна
використовувати програму абсолютно у різних напрямках і з різними цілями.
Наприклад люди,що працюють з фінансами або їх робота так чи інакше зв’язана з
курсами валют можуть використовувати парсер для перегляду та сбору інформації
щодо вартості гривні відносно долару, євро чи рубля
На основі даних, що вона демонструє,
можна також будувати звіти, демонструвати статистику, та будувати графіки
падіння або підвищення курсу. Програма є актуальною, оскільки за останній час
курс гривні мав тенденцію до різкого падіння. А парсер дозволяє відстежувати ці
зміни та робити певні висновки, виходячи з цього. Об’єкт моєї курсової роботи є
також дуже функціональним в плані користувачів. Дана програма може бути
корисною для кожної людини, особливо для тих хто має певні збереження в банківських
установах або бажає відкрити рахунок у певній валюті або ж обміняти свої
збереження.
Програма виконує збір інформації з
сайту finance.i.ua , де розташована вся інформація щодо курсів валют у вигляді
XML файлу. Програма бере за основу та шукає інформацію саме з цього файлу, який
постійно оновлюється. У даному файлі також присутня інформація щодо
банків(телефон,адреса,місто і т.д.).
Звичайно, програма може працювати
лише за наявності інтернет-з'єднання, оскільки всю інформацію вона приймає від
веб сайту, але це сприяє актуальності та коректності поданої інформації.
Отже програма є дуже актуальною в даний момент, корисною та зрозумілою для
кожного звичайного користувача.
Перелік посилань
http://csparser.codeplex.com/://easylab.net.ua/csharp-wf/pishem-parser-na-c://msdn.microsoft.com/en-us/library/bb332338.aspx.ru/post/112325/://msdn.microsoft.com/en-us/library/ms733069%28v=vs.110%29.aspx://stackoverflow.com/questions/846994/how-to-use-html-agility-pack://www.codeproject.com/Articles/123067/A-Simple-Sample-WCF-Service://www.c-sharpcorner.com/UploadFile/0c1bb2/consuming-wcf-service-in-wpf-application/