Erweiterte Möglichkeiten mit Web API (Teil 4)
Kommentare

Formatter mit HttpClient verwenden
Um auch clientseitig Formate jenseits von JSON und XML zu verwenden, ist, wie in Listing 9 gezeigt, eine Liste mit Formattern, die beim Senden verwendet werden sollen,

Formatter mit HttpClient verwenden

Um auch clientseitig Formate jenseits von JSON und XML zu verwenden, ist, wie in Listing 9 gezeigt, eine Liste mit Formattern, die beim Senden verwendet werden sollen, dem Konstruktor von HttpRequestMessage zu übergeben. Eine Liste mit Formatter, die beim Deserialisieren der empfangenen Daten Verwendung finden sollen, kann darüber hinaus beim Aufruf von ReadAsync angeführt werden. Den Mime Type der zu sendenden Nachricht gibt der Entwickler über den Kopfzeileneintrag Content-Type an; jenen, den er sich für die Antwort erwartet mittels Accept.

Listing 9
var url = "http://localhost:1283/api/Hotels";
 
// Liste mit Formatter bereitstellen
var formatters = new List();
formatters.Add(new FlatFileFormatter());
 
var hotel = new Hotel
{
    HotelId = 100,
    Bezeichnung = "Hotel zur Bruchbude",
    Sterne = 1
};

var client = new HttpClient();
var request = new HttpRequestMessage>(new List { hotel }, new MediaTypeHeaderValue("text/plain"), formatters);
 
 
//request.Method = HttpMethod.Post; 
request.Method = new HttpMethod("X-ECHO");
request.RequestUri = new Uri(url);
 
request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
 
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de-DE"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de-AT"));
 
// Anfrage senden
client.SendAsync(request).ContinueWith(task =>
{
    Console.WriteLine("Status: " + task.Result.StatusCode);
    Console.WriteLine("Location: " + task.Result.Headers.Location);
    task.Result.Content.ReadAsAsync>(formatters).ContinueWith(task2 => {
        var hotels = task2.Result;
 
        foreach (var h in hotels)
        {
            Console.WriteLine(h.Bezeichnung);
        }
    });
});  
Querschnittsfunktionen mit Message Handler

Um zu verhindern, dass der Entwickler allgemeine Logiken, wie Sicherheitsprüfungen oder Protokollierungen, in jeder Methode wiederholen muss, kann er solche Querschnittsfunktionen in Subklassen von DelegatingHandler auslagern. Die gewünschte Logik ist dabei innerhalb der zu überschreibenden Methode SendAsync zu hinterlegen. Ein Beispiel dafür findet sich in Listing 10. Der hier gezeigte LoggingHandler gibt Informationen über den aktuellen Methodenaufruf im Debug-Fenster aus. Anschließend wird base.SendAsync aufgerufen. Diese Methode veranlasst Web API, den nächsten konfigurierten DelegatingHandler zur Ausführung zu bringen. Existiert kein weiterer DelegatingHandler, stößt base.SendAsync die eigentliche Servicemethode an. Somit sind Aktionen, die vor dem Ausführen der Servicemethode stattfinden sollen, vor diesem Aufruf zu platzieren, und jene, die Web API erst danach zur Ausführung bringen soll, danach.

Listing 10
public class LoggingHandler : DelegatingHandler 
{
    protected override Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        Debug.WriteLine("Begin Request: {0} {1}", request.Method, request.RequestUri);
        return base.SendAsync(request, cancellationToken);
    }
}  

Einen weiteren interessanten DelegatingHandler, der der Beispielsammlung des Produktteams entnommen wurde, findet man in Listing 11. Er ist für Fälle gedacht, in denen Firewalls HTTP-Verben wie DELETE blocken. Zur Umgehung dieses Problems hat es sich eingebürgert, statt dieser Verben das allgemein akzeptierte Verb POST heranzuziehen und mit einem Kopfzeileneintrag X-HTTP-Method-Override das eigentlich gewünschte Verb anzuzeigen. Dazu prüft der gezeigte MethodOverrideHandler, ob der Aufrufer POST verwendet und ob er ein erlaubtes Verb mit X-HTTP-Method-Override angegeben hat. Ist das der Fall, ändert der Handler das Verb der Anfrage auf das gewünschte ab.

Listing 11
public class MethodOverrideHandler : DelegatingHandler
{    
    readonly string[] _methods = { "DELETE", "HEAD", "PUT" };
    const string _header = "X-HTTP-Method-Override";
    protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)    {
        // Check for HTTP POST with the X-HTTP-Method-Override header.
        if (request.Method == HttpMethod.Post && request.Headers.Contains(_header))        {
            // Check if the header value is in our methods list. 
            var method = request.Headers.GetValues(_header).FirstOrDefault();
            if (_methods.Contains(method, StringComparer.InvariantCultureIgnoreCase))
            { 
                // Change the request method. 
                request.Method = new HttpMethod(method);
            }
        }
        return base.SendAsync(request, cancellationToken);
    }
}  

Auch benutzerdefinierte DelegatingHandler müssen Web API bekannt gemacht werden, zum Beispiel innerhalb der Datei Global.asax. Den dazu heranzuziehenden Methodenaufruf spiegelt Listing 12 wider.

Listing 12
GlobalConfiguration.Configuration
                       .MessageHandlers.Add(new MethodOverrideHandler());
GlobalConfiguration.Configuration.MessageHandlers.Add(new LoggingHandler());  

Das erwartet Sie auf den kommenden Seiten:

  • Handler mit HttpClient
  • Services mit Self Hosting
  • SSL für Web API ohne IIS
  • Fazit
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -