Die RestClient-Bibliothek bietet einen einfachen Connector für die Nutzung von REST-Diensten.
Um es in Ihrem Projekt zu verwenden, fügen Sie das Mafe.RestClient NuGet-Paket zu Ihrem Projekt hinzu.
Das Ziel von RestClient ist es, Entwicklern die einfache Verbindung zu jedem Server auf wirklich einfache Weise zu ermöglichen. Definieren Sie einfach Ihr Data Transfer Object (Dto) und beginnen Sie mit dem Client zu spielen!
Verwenden Sie die Build()-Methode, um einen RestBuilder aus Rest zu erstellen:
var rest = Rest . Build ( ) ;
Um einen einfachen Get-Aufruf zu erstellen, gehen Sie einfach wie folgt vor:
var rest = Rest . Build ( ) ;
var result = rest . Url ( "[URL]" ) . Get ( ) ;
oder wir können die GetAsync()-Methode verwenden:
var rest = Rest . Build ( ) ;
var result = await rest . Url ( "[URL]" ) . GetAsync ( ) ;
Wenn Sie in diesem Dokument das Wort „[URL]“ finden, bezieht es sich auf die Basis-URL-Definition der webAPI.
Wir können einen Root()-Endpunkt definieren und ihn zum Erstellen der Anfrage verwenden.
public RestBuilder Root ( ) => rest . Url ( "https://mywebapi.mydomain.com" ) ;
und dann können wir es wie folgt verwenden:
public RestBuilder Root ( ) => Rest . Build ( ) . Url ( "https://mywebapi.mydomain.com" ) ;
var result = Root ( )
. Command ( "/my-action" )
. Payload ( "mystring" )
. Post ( ) ;
Um RestProperties zum Konfigurieren Ihres Rest-Root-Punkts zu verwenden. Um eine einfache Konfiguration zu erstellen, gehen Sie einfach wie folgt vor:
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 )
} ;
Verwenden Sie die Build()-Methode mit Eigenschaften, um einen RestBuilder aus Rest zu erstellen:
var rest = Rest . Build ( properties ) ;
Die Validierung von X.509-Zertifikaten ist unerlässlich, um sichere SSL/TLS-Sitzungen zu erstellen, die nicht anfällig für Man-in-the-Middle-Angriffe sind.
Die Validierung der Zertifikatskette umfasst die folgenden Schritte:
Es wird nicht empfohlen, das Rad durch die Implementierung einer benutzerdefinierten Zertifikatskettenvalidierung neu zu erfinden.
TLS-Bibliotheken stellen integrierte Zertifikatsvalidierungsfunktionen bereit, die verwendet werden sollten.
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 ( ) ;
Gemäß HTTP/1.1 [RFC2617] sollte die Anwendung das access_token direkt im Autorisierungsanforderungsheader senden. Sie können dies tun, indem Sie den access_token-Wert des Bearer-Tokens als „Authorization: Bearer {access_token_value}“ in den HTTP-Anfragetext aufnehmen.
Wenn ein authentifizierter Benutzer über ein abgelaufenes Zugriffstoken oder Aktualisierungstoken eines Inhabertokens verfügt, wird der Fehler „401 – Nicht autorisiert (ungültiges oder abgelaufenes Aktualisierungstoken)“ zurückgegeben.
var result = Rest . Build ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. Url ( "[URL]" )
. Get ( ) ;
Ein gültiges Bearer-Token (mit aktiven access_token- oder restart_token-Eigenschaften) hält die Authentifizierung des Benutzers aufrecht, ohne dass er seine Anmeldeinformationen häufig erneut eingeben muss. Das access_token kann so lange verwendet werden, wie es aktiv ist, d. h. bis zu einer Stunde nach der Anmeldung oder Erneuerung. Der Refresh_token ist 336 Stunden (14 Tage) aktiv. Nachdem das access_token abgelaufen ist, kann ein aktives restart_token verwendet werden, um ein neues access_token/refresh_token-Paar abzurufen, wie im folgenden Beispiel gezeigt. Dieser Zyklus kann bis zu 90 Tage dauern, danach muss sich der Benutzer erneut anmelden. Wenn das Refresh_token abläuft, können die Token nicht erneuert werden und der Benutzer muss sich erneut anmelden.
Um ein Token zu aktualisieren, verwenden Sie automatisch „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 ( ) ;
Ein Refresh_token sollte widerrufen werden:
Die NetworkCredential-Klasse ist eine Basisklasse, die Anmeldeinformationen in kennwortbasierten Authentifizierungsschemata wie Basic, Digest, NTLM und Kerberos bereitstellt. Klassen, die die ICredentials-Schnittstelle implementieren, z. B. die CredentialCache-Klasse, geben NetworkCredential-Objekte zurück. Diese Klasse unterstützt keine auf öffentlichen Schlüsseln basierenden Authentifizierungsmethoden wie die Secure Sockets Layer (SSL)-Clientauthentifizierung.
var result = Rest . Build ( )
. NetworkCredential ( "myUsername" , "myPassword" )
. Url ( "[URL]" )
. Get ( ) ;
var result = rest
. NetworkCredential ( ( ) => new System . Net . NetworkCredential ( "myUsername" , "myPassword" ) )
. Url ( "[URL]" )
. Get ( ) ;
Die Headers-Sammlung enthält die mit der Anforderung verknüpften Protokollheader. Mit der Methode Header((h)=>{}) können Sie die Liste der Schlüssel hinzufügen.
var result = Rest . Build ( )
. Header ( ( h ) => {
if ( ! h . Contains ( "auth-custom" ) )
h . Add ( "auth-custom" , "value" ) ;
} )
. Url ( "[URL]" )
. Get ( ) ;
Zwei Arten der Serialisierung werden von RestClient unterstützt: XML und Json. Es ist jedoch möglich, ISerializerContent zu implementieren, um die Serialisierung anzupassen. RestClient verwendet .Json(), um ein Objekt in JSON zu serialisieren.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( )
. Get < ResponseObject > ( ) ;
Es ist möglich, JSON-Serializer-Optionen wie folgt an die .Json()-Methode zu übergeben:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerOptions {
WriteIndented = true
} )
. Get < ResponseObject > ( ) ;
Der obige Snippet-Code berücksichtigt die Verwendung der System.Text.Json-Bibliothek. Wenn wir Netwnsoft wie folgt verwenden:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerSettings {
Formatting = Formatting . Indented
} )
. Get < ResponseObject > ( ) ;
RestClient verwendet .Xml(), um ein Objekt in XML zu serialisieren.
var result = rest
. Url ( "[URL]" )
. Xml ( )
. Get < ResponseObject > ( ) ;
Es ist möglich, die Einstellungen wie folgt an die Methode .Xml() zu übergeben:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Xml ( new XmlReaderSettings { Indent = true } , new XmlWriterSettings { IgnoreWhitespace = true } )
. Get < ResponseObject > ( ) ;
Nachfolgend ein Beispiel, wie Sie eine benutzerdefinierte Serialisierung durchführen können, indem Sie die ISerializerContent-Schnittstelle implementieren:
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 ( ) ;
}
}
Jetzt können wir MyCustomSerializer wie folgt verwenden:
var result = Rest . Build ( )
. Url ( "[URL]" )
. CustomSerializer ( new MyCustomSerializer { } )
. Get < ResponseObject > ( ) ;
BufferSize kann verwendet werden, um die Puffergröße während des Upload- und Download-Streams festzulegen. Der Standardwert ist 80 KB
var result = Rest . Build ( )
. Url ( "[URL]" )
. BufferSize ( 4096 * 5 * 5 ) //100Kb
. Get ( ) ;
Aktiviert die GZIP-Komprimierung während der Kommunikation mit einer angegebenen Ressource:
var result = Rest . Build ( )
. Url ( "[URL]" )
. EnableGZipCompression ( )
. Get ( ) ;
Die Bibliothek dekomprimiert die Antwort automatisch.
GET ist eine der gebräuchlichsten HTTP-Methoden und GET wird verwendet, um Daten von einer bestimmten Ressource anzufordern
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Get ( ) ;
var result = await rest
. Url ( "[URL]" )
. GetAsync ( ) ;
Einige weitere Hinweise zu GET-Anfragen:
Beachten Sie, dass die Abfragezeichenfolge (Name/Wert-Paare) in der URL einer GET-Anfrage gesendet wird.
In einigen Fällen müssen wir Argumente als Abfragezeichenfolge verwenden. Wir können die Methode Parameter(key, value) verwenden, um es wie folgt aufzulösen:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/path" )
. Parameter ( "id" , "10" )
. Parameter ( "type" , "myType" )
. Get ( ) ;
Die generierte URL lautet: [URL]/path?id=10&type=myType
POST wird verwendet, um Daten an einen Server zu senden, um eine Ressource zu erstellen/aktualisieren. Die mit POST an den Server gesendeten Daten werden im Request-Payload der HTTP-Anfrage gespeichert:
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 ist eine weitere gängige HTTP-Methode, die verwendet wird, um:
PUT wird verwendet, um Daten an einen Server zu senden, um eine Ressource zu erstellen/aktualisieren.
Der Unterschied zwischen POST und PUT besteht darin, dass PUT-Anfragen idempotent sind. Das heißt, dass der mehrfache Aufruf derselben PUT-Anfrage immer zum gleichen Ergebnis führt. Im Gegensatz dazu hat das wiederholte Aufrufen einer POST-Anfrage den Nebeneffekt, dass dieselbe Ressource mehrmals erstellt wird.
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 > ( ) ;
Die DELETE-Methode löscht die angegebene Ressource.
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 > ( ) ;
Die DOWNLOAD-Methode lädt die angegebene Ressource herunter.
var result = Rest . Build ( )
. Download ( "[URL]" ) ;
var result = await rest
. DownloadAsync ( "[URL]" ) ;
Es ist möglich, den Download-Status mit OnDownloadProgress anzuzeigen.
var rest = Rest . Build ( ) ;
var result = await rest
. OnDownloadProgress ( ( d ) => Console . WriteLine ( $ " { d . CurrentBytes } / { d . TotalBytes } " ) )
. DownloadAsync ( "[URL]" ) ;
Gibt die Benachrichtigung weiter, dass Vorgänge abgebrochen werden sollten.
Ein CancellationToken ermöglicht den kooperativen Abbruch zwischen Threads, Thread-Pool-Arbeitselementen oder Task-Objekten. Sie erstellen ein Stornierungstoken, indem Sie ein CancellationTokenSource-Objekt instanziieren, das von seiner CancellationTokenSource abgerufene Stornierungstoken verwaltet.
Im folgenden Beispiel wird ein Abbruchtoken verwendet, um die Ausführung zu stoppen:
// 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 ) ;
Nach der angeforderten Stornierung wird eine TaskCancellatedException ausgelöst. Die Ausnahme wird in das RestResult-Objekt gekapselt.
Die CUSTOM-Methode, die die angegebene Ressource anpasst.
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 verwendet die Playload(obj)-Methode, um ein Objekt auf Anfrage festzulegen:
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 > ( ) ;
Bei Bedarf können wir die Anfrage als Formular-URL-codiert verwenden. Um es zu verwenden, müssen wir es wie folgt aktivieren:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. EnableFormUrlEncoded ( true )
und dann können wir die Parameter als Wörterbuch übergeben:
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 ( ) ;
Es ist möglich, die Parameter innerhalb des Handlers zu übergeben und die Form-URL-Verschlüsselung zu aktivieren:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. FormUrlEncoded ( true , ( p ) =>
{
p . Add ( "key1" , "value1" ) ;
p . Add ( "key2" , "value2" ) ;
} )
. Post ( ) ;
OnUploadProgress tritt auf, wenn die Anforderung ausgeführt wird und die Daten ausgegeben werden. Wir können einen Prozentsatz der hochgeladenen Daten wie folgt ermitteln:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnUploadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during request
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnDownloadProgress tritt auf, wenn die Antwort ausgeführt wird und die Daten eingehen. Wir können einen Prozentsatz der heruntergeladenen Daten wie folgt ermitteln:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnDownloadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during response
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
Der Standardwert beträgt 100.000 Millisekunden (100 Sekunden). Um ein unendliches Timeout festzulegen, legen Sie den Eigenschaftswert auf InfiniteTimeSpan fest. Es kann bis zu 15 Sekunden dauern, bis eine DNS-Anfrage (Domain Name System) zurückgegeben wird oder eine Zeitüberschreitung auftritt. Wenn Ihre Anfrage einen Hostnamen enthält, der aufgelöst werden muss, und Sie Timeout auf einen Wert von weniger als 15 Sekunden festlegen, kann es 15 Sekunden oder länger dauern, bis eine Ausnahme ausgelöst wird, die auf eine Zeitüberschreitung Ihrer Anfrage hinweist.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( 3200 ) //milliseconds
. Get < ResponseObject > ( ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( TimeSpan . FromMinutes ( 10 ) )
. Get < ResponseObject > ( ) ;
OnStart ist ein Ereignis, das ausgelöst wird, wenn die Anfrage startet.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnStart ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentRequestAsString ist ein Ereignis, das ausgelöst wird, wenn die Anfrage bereit ist und noch nicht gesendet wurde.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentRequestAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentResponseAsString ist ein Ereignis, das ausgelöst wird, wenn die Antwort empfangen wird und noch nicht deserialisiert ist.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentResponseAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreResult tritt auf, wenn die Anforderung abgeschlossen wird, aber noch nicht abgeschlossen ist. Wenn OnPreResult ausgelöst wird, können wir etwas tun, zum Beispiel das Ergebnis einer Anfrage abrufen und verwenden.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreCompleted ( ( r ) => {
DoSomethings ( r . Result ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnException tritt auf, wenn die Anforderung eine Ausnahme auslöst.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnException ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnCompleted tritt ein, wenn die Anforderung abgeschlossen ist.
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnCompleted ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
RestClient ermöglicht die Erstellung einer flexiblen und robusten Netzwerkschicht und ist sehr einfach zu verwenden. Nachfolgend finden Sie eine vollständige Codedemonstration und ein vollständiges Codebeispiel.
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 > ( ) ;
}