5.2. XML-RPC mit C#

In C# kann die WebRequest Klasse für Anfragen an die XML-RPC Schnittstelle verwendet werden, allerdings muss hierbei die Authentifizierung explizit als HTTP-Header mit gesendet werden, da die Credentials der WebRequest Klasse nur gesendet werden, nachdem der Server eine Anfrage mit dem HTTP Statuscode 401 beantwortet hat.
Die folgende Klasse kann als Basis für Anfragen an die GREYHOUND XML-RPC Schnittstelle verwendet werden:
C# GreyhoundClient:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

class GreyhoundClient
{
  public string Url;
  public string ClientId;
  public WebProxy Proxy;

  private string Authorization;

  public GreyhoundClient(string host, int port, bool ssl, string username, string password, bool acceptAllSslCertificates = false)
  {
    // URL zur API zusammensetzen:
    Url = (ssl ? "https" : "http") + "://" + host + ":" + port + "/xmlrpc/";

    // Client ID (32 Zeichen) erzeugen:
    string clientIdChars = "0123456789ABCDEF";
    StringBuilder stringBuilder = new StringBuilder();
    Random random = new Random();

    for (int i = 0; i < 32; i++)
    stringBuilder.Append(clientIdChars[random.Next(0, clientIdChars.Length)]);

    ClientId = stringBuilder.ToString();

    // Zugangsdaten merken:
    Authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(ClientId + "-" + username + ":" + password));

    if (acceptAllSslCertificates)
      ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(AcceptAllCertificates);
  }

  public string SendXmlRequest(string method, string paramsXml)
  {
    string xml = "<?xml version=\"2.0\" encoding=\"utf-8\"?>\r\n<methodCall><methodName>" + method + "</methodName><params>" + paramsXml + "</params></methodCall>";
    byte[] xmlBytes = Encoding.UTF8.GetBytes(xml);
    WebRequest request = WebRequest.Create(Url);
    request.Method = "POST";

    // Authentifizierung:
    // Die Credentials Eigenschaft funktioniert nicht, da der Request dann zunächst ohne Authentifizierung geschickt wird und erwartet wird,
    // dass der Server die Authentifzierung mit einem 401 Status-Code beantwortet. Daher senden wir die Authentifizierung explizit als Header mit:
    request.Headers[HttpRequestHeader.Authorization] = Authorization;

    if (Proxy != null)
      request.Proxy = Proxy;

    request.ContentType = "text/xml; charset=UTF-8";
    request.ContentLength = xmlBytes.Length;
    Stream requestStream = request.GetRequestStream();

    try {
      requestStream.Write(xmlBytes, 0, xmlBytes.Length);
    }
    finally {
      requestStream.Close();
    }

    WebResponse response = request.GetResponse();

    try
    {
      StreamReader reader = new StreamReader(response.GetResponseStream());

      try
      {
        return reader.ReadToEnd();
      }
      finally
      {
        reader.Close();
      }
    }
    finally
    {
      response.Close();
    }
  }

  private static bool AcceptAllCertificates(object sender, X509Certificate certification, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  {
    return true;
  }
}