.Net und WebRequest mit Authentifizerung

WebRequest in C# abzusetzten ist mit den Bibliotheken recht einfach geworden. Aber wenn es dann mal mehr wird, als nur ein einfacher Download wird es schon wieder schwieriger. Daher hier eine kurze Anleitung, wie so ein Request bearbeitet wird.

Zuerst muss ein WebRequest erstellt werden:

var webReq = (HttpWebRequest)HttpWebRequest.Create("http://example.com/");

Dann muss unterschieden werden, ob es ein laden einer Website ist, oder ob senden von Daten an die Website ist. Bei laden einer Website wird häufig die GET-Methode verwendet, siehe hier:

webReq.Method = "GET"; // Ein einfache Get-Befehl, mit Parameter in der URL ala: example.com?param1=val1&param2=val2
// Request abschicken und Antwort auswerten 
try {
  // Beim GetResponse() fliegen die Fehlermeldungen, die der Server zurückgibt, wie 404 (Datei nicht gefunden) oder 401 (Nicht Authentifiziert)
  var webRes = (HttpWebResponse)webReq.GetResponse();
  // und nun den Stream lesen
  using (var streamer = webReq.GetResponseStream()) {
    // Hier kann man nun anhand von webRes.ContentType unterschiedlich die Daten verarbeitetn, z.B.: bei "text/xml" mit einem (new XmlDocument()).Load(streamer); alles in ein Xml-Objekt packen
  }
}
catch (WebException exc) {
  // Exceptions verarbeiten
}

Für die einfache übermittlung von Variablen mit der POST-Methode, hier noch ein Code-Schnipsel:

webReq.Method = "POST";
webReq.ContentType = "application/x-www-form-urlencoded";
// Variablen zusammenbauen und in Byte-Array wandeln um es auf den Stream schreiben zu können
var postData = "variable1=val1&variable2=val2";
var postBytes = Encoding.UTF8.GetBytes(postData);

// Länge der Daten mitgeben und diese nun auf den Stream schreiben
webReq.ContentLength = postBytes.Length;
var stream = webReq.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);

// Request abschicken und Antwort auswerten (wie bei GET-Methode)
try {
  // Beim GetResponse() fliegen die Fehlermeldungen, die der Server zurückgibt, wie 404 (Datei nicht gefunden) oder 401 (Nicht Authentifiziert)
  var webRes = (HttpWebResponse)webReq.GetResponse();
  // und nun den Stream lesen
  using (var streamer = webReq.GetResponseStream()) {
    // Hier kann man nun anhand von webRes.ContentType unterschiedlich die Daten verarbeitetn, z.B.: bei "text/xml" mit einem (new XmlDocument()).Load(streamer); alles in ein Xml-Objekt packen
  }
}
catch (WebException exc) {
  // Exceptions verarbeiten
}

Dann gibt es aber noch die Probleme mit den Anmeldungen an dem WebServer, die mit folgenden Quellcode-Stücken gelöst werden können:

// Um die aktuelle Anmeldung zu benutzen (Häufig im Intranet möglich)
request.UseDefaultCredentials = true;
// Für eine explizite Netzwerkidentifikation (Via Domain)
request.Credentials = new NetworkCredential("username", "password");
// Für eine HTTP-Authentifizierung (Wird häufig via .htaccess parametriert)
var auth = Encoding.UTF8.GetBytes("user:password");
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(auth);

// Und ein Übel gibt es noch, wenn man einen Server besitzt der zwar mit SSL-Zertifikaten ausgestattet ist, aber 
// keine Root-Zertifikate besitzt, kann mit nachfolgenden Code, mit diesen Server trotzdem reden:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// Wobei hier zu bedenken ist, dass nun alle Zertifikate angenommen werden, man könnte hier noch eine passende Prüfung einbauen

Wenn Dateien an einen Website hochgeladen werden sollen, wird das ganze etwas schwieriger, daher habe ich dafür eine Klasse gebaut, die man unter nachfolgenden Link herunterladen kann: HttpFileUploader.
Hier noch eine Beispiel-Verwendung:

// Objekt erstellen
var fileUploader = new HttpFileUploader("http://example.com/upload");
// Parameter setzten
fileUploader.SetParam("LastModifiedSource", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
fileUploader.SetParam("Name", "ExampleName");
fileUploader.SetParam("Designation", "ExampleDesignation");
// XML-Datei setzten
var xmlfile = System.Text.Encoding.Unicode.GetBytes(xmlString);
fileUploader.SetFile("xmlfile", "xmlfile.xml", xmlfile, "text/xml");
// Bild setzen
fileUploader.SetFile("picture", "picture.png", pictureBytes, "image/png");
// Upload durchfuehren
var ret = fileUploader.SendRequest();