Библиотека RestClient предоставляет простой соединитель для использования служб REST.
Чтобы использовать его в своем проекте, добавьте в свой проект пакет NuGet Mafe.RestClient.
Цель RestClient — предоставить разработчикам возможность легко и просто подключаться к любому серверу. Просто определите свой объект передачи данных (Dto) и начните играть с клиентом!
Используйте метод Build() для создания RestBuilder из Rest:
var rest = Rest . Build ( ) ;
Чтобы создать простой вызов get, просто сделайте следующее:
var rest = Rest . Build ( ) ;
var result = rest . Url ( "[URL]" ) . Get ( ) ;
или мы можем использовать метод GetAsync():
var rest = Rest . Build ( ) ;
var result = await rest . Url ( "[URL]" ) . GetAsync ( ) ;
Всякий раз, когда вы встречаете слово «[URL]» в этом документе, оно относится к базовому определению URL-адреса веб-API.
Мы можем определить конечную точку Root() и использовать ее для построения запроса.
public RestBuilder Root ( ) => rest . Url ( "https://mywebapi.mydomain.com" ) ;
и затем мы можем использовать его вот так:
public RestBuilder Root ( ) => Rest . Build ( ) . Url ( "https://mywebapi.mydomain.com" ) ;
var result = Root ( )
. Command ( "/my-action" )
. Payload ( "mystring" )
. Post ( ) ;
Чтобы использовать RestProperties для настройки корневой точки отдыха. Чтобы создать простую конфигурацию, например:
RestProperties properties = new RestProperties
{
EndPoint = new Uri ( "[URL]" ) , //if you use .Url("[URL]") you override it
BufferSize = 4096 ,
CertificateOption = ClientCertificateOption . Manual ,
Timeout = TimeSpan . FromMinutes ( 2 )
} ;
Используйте метод Build() со свойствами для создания RestBuilder из Rest:
var rest = Rest . Build ( properties ) ;
Проверка сертификатов X.509 необходима для создания безопасных сеансов SSL/TLS, не уязвимых для атак «человек посередине».
Проверка цепочки сертификатов включает в себя следующие шаги:
Не рекомендуется изобретать велосипед, реализуя собственную проверку цепочки сертификатов.
Библиотеки TLS предоставляют встроенные функции проверки сертификатов, которые следует использовать.
List < string > validCerts = new List < string > ( ) {
"CERT STRING"
} ;
var result = Rest . Build ( )
. CertificateValidation ( ( sender , certificate , chain , errors ) =>
{
// for development, trust all certificates
if ( development ) return true ;
// Compliant: trust only some certificates
return errors == SslPolicyErrors . None
&& validCerts . Contains ( certificate . GetCertHashString ( ) ) ;
} )
. Url ( "[URL]" )
. Get ( ) ;
Как определено HTTP/1.1 [RFC2617], приложение должно отправлять access_token непосредственно в заголовке запроса авторизации. Это можно сделать, включив значение access_token токена-носителя в текст HTTP-запроса как «Авторизация: носитель {access_token_value}».
Если у аутентифицированного пользователя есть access_token илиrefresh_token токена-носителя, срок действия которого истек, то возвращается ошибка «401 — Неавторизованный (недействительный или просроченный токен обновления)».
var result = Rest . Build ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. Url ( "[URL]" )
. Get ( ) ;
Действительный токен носителя (с активными свойствами access_token илиrefresh_token) поддерживает аутентификацию пользователя, не требуя от него частого повторного ввода своих учетных данных. Access_token можно использовать до тех пор, пока он активен, то есть до одного часа после входа в систему или продления. Refresh_token активен в течение 336 часов (14 дней). По истечении срока действия access_token активныйrefresh_token можно использовать для получения новой пары access_token/refresh_token, как показано в следующем примере. Этот цикл может продолжаться до 90 дней, после чего пользователь должен снова войти в систему. Если срок действия Refresh_token истекает, токены не могут быть продлены, и пользователь должен снова войти в систему.
Чтобы обновить токен, используйте «RefreshTokenInvoke» автоматически.
var url = "[URL]" ;
var result = Rest . Build ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. RefreshToken ( true )
. RefreshTokenInvoke ( async ( ) =>
{
var result = await rest
. Url ( url )
. Command ( "/refresh" )
. GetAsync < TokenObjectResponse > ( ) ;
doSomethings ( ) ; //store the token inside your env.
return result ;
} )
. Command ( "/detail" )
. Url ( url )
. Get ( ) ;
Refresh_token должен быть отозван:
Класс NetworkCredential — это базовый класс, который предоставляет учетные данные в схемах аутентификации на основе пароля, таких как базовая, дайджест, NTLM и Kerberos. Классы, реализующие интерфейс ICredentials, такие как класс CredentialCache, возвращают объекты NetworkCredential. Этот класс не поддерживает методы проверки подлинности на основе открытого ключа, такие как проверка подлинности клиента Secure Sockets Layer (SSL).
var result = Rest . Build ( )
. NetworkCredential ( "myUsername" , "myPassword" )
. Url ( "[URL]" )
. Get ( ) ;
var result = rest
. NetworkCredential ( ( ) => new System . Net . NetworkCredential ( "myUsername" , "myPassword" ) )
. Url ( "[URL]" )
. Get ( ) ;
Коллекция Headers содержит заголовки протоколов, связанные с запросом. Метод Header((h)=>{}) позволяет добавить список ключей.
var result = Rest . Build ( )
. Header ( ( h ) => {
if ( ! h . Contains ( "auth-custom" ) )
h . Add ( "auth-custom" , "value" ) ;
} )
. Url ( "[URL]" )
. Get ( ) ;
RestClient поддерживает два типа сериализации: Xml и Json, но можно реализовать ISerializerContent для настройки сериализации. RestClient использует .Json() для сериализации объекта в json.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( )
. Get < ResponseObject > ( ) ;
В метод .Json() можно передать параметры сериализатора json, например:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerOptions {
WriteIndented = true
} )
. Get < ResponseObject > ( ) ;
В приведенном выше фрагменте кода рассматривается использование библиотеки System.Text.Json. Если мы используем Netwnsoft следующим образом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerSettings {
Formatting = Formatting . Indented
} )
. Get < ResponseObject > ( ) ;
RestClient использует .Xml() для сериализации объекта в xml.
var result = rest
. Url ( "[URL]" )
. Xml ( )
. Get < ResponseObject > ( ) ;
Можно передать настройки методу .Xml(), например так:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Xml ( new XmlReaderSettings { Indent = true } , new XmlWriterSettings { IgnoreWhitespace = true } )
. Get < ResponseObject > ( ) ;
Ниже приведен пример того, как вы можете выполнить пользовательскую сериализацию, реализовав интерфейс ISerializerContent:
public class MyCustomSerializer : ISerializerContent
{
public string MediaTypeAsString => throw new NotImplementedException ( ) ;
public object DeserializeObject ( string value , Type typeOf , object options = null )
{
throw new NotImplementedException ( ) ;
}
public string SerializeObject ( object value , Type typeOf , object options = null )
{
throw new NotImplementedException ( ) ;
}
}
Теперь мы можем использовать MyCustomSerializer следующим образом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. CustomSerializer ( new MyCustomSerializer { } )
. Get < ResponseObject > ( ) ;
BufferSize можно использовать для установки размера буфера во время потока загрузки и скачивания. Значение по умолчанию — 80 КБ.
var result = Rest . Build ( )
. Url ( "[URL]" )
. BufferSize ( 4096 * 5 * 5 ) //100Kb
. Get ( ) ;
Включает сжатие gzip во время связи с указанным ресурсом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. EnableGZipCompression ( )
. Get ( ) ;
Библиотека автоматически распаковывает ответ.
GET — один из наиболее распространенных методов HTTP, и GET используется для запроса данных из указанного ресурса.
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Get ( ) ;
var result = await rest
. Url ( "[URL]" )
. GetAsync ( ) ;
Некоторые другие примечания по запросам GET:
Обратите внимание, что строка запроса (пары имя/значение) отправляется в URL-адресе запроса GET.
В некоторых случаях нам необходимо использовать аргументы в качестве строки запроса. Мы можем использовать метод Параметр(ключ, значение) для решения этой проблемы следующим образом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/path" )
. Parameter ( "id" , "10" )
. Parameter ( "type" , "myType" )
. Get ( ) ;
Сгенерированный URL-адрес: [URL]/path?id=10&type=myType.
POST используется для отправки данных на сервер для создания/обновления ресурса. Данные, отправленные на сервер с помощью POST, сохраняются в полезных данных HTTP-запроса:
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Post < ResponseObject > ( ) ;
var result = await rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. PostAsync < ResponseObject > ( ) ;
Post — еще один распространенный HTTP-метод, который используется для:
PUT используется для отправки данных на сервер для создания/обновления ресурса.
Разница между POST и PUT заключается в том, что запросы PUT идемпотентны. То есть вызов одного и того же запроса PUT несколько раз всегда будет давать один и тот же результат. Напротив, повторный вызов запроса POST имеет побочные эффекты, связанные с созданием одного и того же ресурса несколько раз.
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Put < ResponseObject > ( ) ;
var result = await rest
. Url ( "[URL]" )
. Payload ( new Object { } )
. PutAsync < ResponseObject > ( ) ;
Метод DELETE удаляет указанный ресурс.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Delete < ResponseObject > ( ) ;
var result = await Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. DeleteAsync < ResponseObject > ( ) ;
Метод DOWNLOAD загружает указанный ресурс.
var result = Rest . Build ( )
. Download ( "[URL]" ) ;
var result = await rest
. DownloadAsync ( "[URL]" ) ;
Возможно отображение статуса загрузки с помощью OnDownloadProgress.
var rest = Rest . Build ( ) ;
var result = await rest
. OnDownloadProgress ( ( d ) => Console . WriteLine ( $ " { d . CurrentBytes } / { d . TotalBytes } " ) )
. DownloadAsync ( "[URL]" ) ;
Распространяет уведомление о том, что операции следует отменить.
CancellationToken обеспечивает совместную отмену между потоками, рабочими элементами пула потоков или объектами Task. Токен отмены создается путем создания экземпляра объекта CancellationTokenSource, который управляет токенами отмены, полученными из его CancellationTokenSource.
В следующем примере для остановки выполнения используется токен отмены:
// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource ( ) ;
CancellationToken token = source . Token ;
// Schedules a cancel operation on this System.Threading.CancellationTokenSource
// after the specified number of milliseconds
token . CancelAfter ( 3000 ) ;
var file1 = Rest . Build ( ) . DownloadAsync ( "[URL FILE1]" , token . Token ) ;
var file2 = Rest . Build ( ) . DownloadAsync ( "[URL FILE2]" , token . Token ) ;
var get1 = Rest . Build ( ) . Url ( "[URL GET1]" ) . GetAsync < MyObject > ( token . Token ) ;
Task . WaitAll ( file1 , file2 , get1 ) ;
После запроса на отмену выдается исключение TaskCancellatedException. Исключение будет инкапсулировано в объект RestResult.
Метод CUSTOM, настраивающий указанный ресурс.
HttpMethod PATCH = new HttpMethod ( "PATCH" ) ;
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. CustomCall < ResponseObject > ( PATCH ) ;
var result = await rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. CustomCallAsync < ResponseObject > ( PATCH ) ;
RestClient использует метод Playload(obj) для установки объекта по запросу:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new RequestObject { } )
. Post < ResponseObject > ( ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new RequestObject { } )
. Put < ResponseObject > ( ) ;
При необходимости мы можем использовать запрос в виде URL-адреса формы. Чтобы использовать его, нам нужно включить его, например:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. EnableFormUrlEncoded ( true )
и затем мы можем передать параметры как словарь:
var params = new Dictionary < string , string > ( ) ;
params . Add ( "key1" , "value1" ) ;
params . Add ( "key2" , "value2" ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. EnableFormUrlEncoded ( true )
. FormUrlEncoded ( params )
. Post ( ) ;
Можно передать параметры внутри обработчика и включить кодировку URL-адреса формы:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. FormUrlEncoded ( true , ( p ) =>
{
p . Add ( "key1" , "value1" ) ;
p . Add ( "key2" , "value2" ) ;
} )
. Post ( ) ;
OnUploadProgress возникает, когда запрос выполняется и данные передаются. Мы можем получить процент загружаемых данных следующим образом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnUploadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during request
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnDownloadProgress происходит, когда выполняется ответ и поступают данные. Мы можем получить процент загружаемых данных следующим образом:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnDownloadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during response
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
Значение по умолчанию — 100 000 миллисекунд (100 секунд). Чтобы установить бесконечный тайм-аут, установите для свойства значение InfiniteTimeSpan. Ответ на запрос системы доменных имен (DNS) может занять до 15 секунд или время ожидания. Если ваш запрос содержит имя хоста, требующее разрешения, и вы установили для параметра Timeout значение менее 15 секунд, может пройти 15 секунд или более, прежде чем будет выдано исключение, указывающее время ожидания вашего запроса.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( 3200 ) //milliseconds
. Get < ResponseObject > ( ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( TimeSpan . FromMinutes ( 10 ) )
. Get < ResponseObject > ( ) ;
OnStart — это событие, которое срабатывает при запуске запроса.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnStart ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentRequestAsString — это событие, которое срабатывает, когда запрос готов, но еще не отправлен.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentRequestAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentResponseAsString — это событие, которое срабатывает, когда ответ получен, и он еще не десериализован.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentResponseAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreResult возникает, когда запрос завершается, но еще не завершен. Когда OnPreResult поднимается, мы можем что-то сделать, например, получить и использовать результат запроса.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreCompleted ( ( r ) => {
DoSomethings ( r . Result ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnException возникает, когда запрос вызывает исключение.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnException ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnCompleted возникает, когда запрос завершен.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnCompleted ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
RestClient позволяет создать гибкий и надежный сетевой уровень, и его очень легко использовать. Ниже вы найдете полную демонстрацию кода и полный пример кода.
public class NetworkService {
//building context
public RestBuilder Root ( )
=> Rest . Build ( )
. CertificateValidation ( ( sender , certificate , chain , errors ) =>
{
if ( development ) return true ;
return errors == SslPolicyErrors . None
&& validCerts . Contains ( certificate . GetCertHashString ( ) ) ;
} )
. Url ( "[URL]" ) ;
public RestBuilder RootAuthentication ( )
=> Root ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. RefreshToken ( )
. RefreshTokenInvoke ( async ( ) => await PostRefreshAsync ( new RefreshRequest { } ) ) ;
public RestBuilder UsersRoot ( )
=> Root ( ) . Command ( "/Users" ) ;
public RestBuilder DimensionsRoot ( )
=> Root ( ) . Command ( "/Dimensions" ) ;
public RestBuilder EventsRoot ( )
=> RootAuthentication ( ) . Command ( "/Events" ) ;
//requests
public async Task < RestResult < LoginResponse > > PostLoginAsync ( LoginRequest request )
=> await UsersRoot ( )
. Command ( "/Login" ) //[URL]/Users/Login
. Payload ( request )
. PostAsync < LoginResponse > ( ) ;
public async Task < RestResult < RuleResponse > > GetRulesAsync ( )
=> await UsersRoot ( )
. Command ( "/Rules" )
. GetAsync < RuleResponse > ( ) ;
public async Task < RestResult < RefreshResponse > > PostRefreshAsync ( RefreshRequest request )
=> await UsersRoot ( )
. Command ( "/Refresh" )
. Payload ( request )
. PostAsync < RefreshResponse > ( ) ;
public async Task < RestResult < CountryResponse > > PostCountriesAsync ( CountryRequest request )
=> await DimensionsRoot ( )
. Command ( "/Countries" )
. Payload ( request )
. PostAsync < CountryResponse > ( ) ;
public async Task < RestResult < EventDetailResponse > > PostEventDetailAsync ( EventDetailRequest request )
=> await EventsRoot ( )
. Command ( "/EventDetail" )
. Payload ( request )
. PostAsync < EventDetailResponse > ( ) ;
}