Da ich keine Lust hatte für jede Art von Resourcen die ich in einem WebBot abrufe (String, Image, Binary, ...) eine extra Methode zu bauen, hab ich mir überlegt eine generische Lösung zu basteln. Die Klasse hat keinen Anspruch eine vollständige Allround Lösung zu sein sondern ist für ein aktuelles Projekt entstanden und hat entsprechende Funktionen.
Länger:
Ganz von alleine gehts natürlich nicht, deswegen kann man für jeden Type einen
angeben welchen den responseStream des WebRequests entsprechend konvertiert.Zuerst hab ich ein Dictionary<Type, Converter<Stream, object>> genutzt, da ich aber eine Lösung ohne casten haben wollte, hab ich nun einen internen, generischen, statischen ConverterProvider definiert welcher für jeden Type einen Converter speichern kann. Damit durchbreche ich zwar die Object Grenze, jedoch ist mir das lieber als immer das Ergebnis noch casten zu müssen.
Für String, Image und Binary gibts schon nen Converter da man diese sehr häufig braucht. Außerdem eine nicht generische Überlandung um das Ergebnis als String zu bekommen.
Sonst, es gibt ne
Überladung für Post Parameter, hat der WebClient, wenn ich mich recht entsinne, auch.Code:
Code:
internal class Http
{
private CookieContainer _cookies = new CookieContainer();
private string _lastPage = string.Empty;
private string _userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0";
public Http()
{
ConverterProvider<string>.Converter = StreamToString;
ConverterProvider<Image>.Converter = StreamToImage;
ConverterProvider<byte[]>.Converter = StreamToByteArr;
}
public string LastPage
{
get
{
return this._lastPage;
}
}
public string UserAgent
{
get
{
return this._userAgent;
}
set
{
this._userAgent = value;
}
}
public void DeleteCookies()
{
_cookies = new CookieContainer();
}
private string NameValueCollectionToString(NameValueCollection postData)
{
StringBuilder sb = new StringBuilder();
string delimiter = String.Empty;
var allKeys = postData.AllKeys;
for (int i = 0; i < postData.Count; ++i)
{
sb.Append(delimiter).Append(allKeys[i]).Append("=").Append(WebUtility.UrlEncode(postData[i]));
delimiter = "&";
}
return sb.ToString();
}
public string WebRequest(string url)
{
return WebRequest<string>(url, string.Empty);
}
public string WebRequest(string url, NameValueCollection postData)
{
return WebRequest<string>(url, NameValueCollectionToString(postData));
}
public string WebRequest(string url, string postData)
{
return WebRequest<string>(url, postData);
}
public TResult WebRequest<TResult>(string url)
{
return WebRequest<TResult>(url, string.Empty);
}
public TResult WebRequest<TResult>(string url, NameValueCollection postData)
{
return WebRequest<TResult>(url, NameValueCollectionToString(postData));
}
public TResult WebRequest<TResult>(string url, string postData)
{
var request = (HttpWebRequest)HttpWebRequest.Create(url);
request.CookieContainer = _cookies;
request.UserAgent = _userAgent;
if (_lastPage != string.Empty)
{
request.Referer = _lastPage;
}
if (postData == string.Empty)
{
request.Method = WebRequestMethods.Http.Get;
}
else
{
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/x-www-form-urlencoded";
byte[] b = Encoding.UTF8.GetBytes(postData);
request.ContentLength = b.LongLength;
using (var postStream = request.GetRequestStream())
{
postStream.Write(b, 0, b.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
_lastPage = response.ResponseUri.AbsoluteUri;
using (var responseStream = response.GetResponseStream())
{
return ConverterProvider<TResult>.Converter(responseStream);
}
}
else
{
throw new WebException(response.StatusDescription);
}
}
}
private static sealed class ConverterProvider<TResult>
{
public static Converter<Stream, TResult> Converter;
}
private static string StreamToString(Stream s)
{
using (var r = new StreamReader(s, Encoding.UTF8))
{
return r.ReadToEnd();
}
}
private static byte[] StreamToByteArr(Stream s)
{
using (var ms = new MemoryStream())
{
s.CopyTo(ms);
return ms.ToArray();
}
}
private static Image StreamToImage(Stream s)
{
return Image.FromStream(s);
}
public void ApplyConverter<TResult>(Converter<Stream, TResult> converter)
{
ConverterProvider<TResult>.Converter = converter;
}
public Cookie GetCookieOrNull(Uri uri, Predicate<Cookie> predicate)
{
foreach (Cookie cookie in _cookies.GetCookies(uri))
{
if (predicate(cookie))
return cookie;
}
return null;
}
}
Also wozu der ganze Aufwand? Hier ein Beispiel um das Guthaben auf Battle.Net abzufragen, welches vom Server als Json zurückgegeben wird.
Code:
Http http = new Http();
if (!Login(http, userMail, password))
throw new Exception("Login");
string mgntPage = http.WebRequest("https://eu.battle.net/account/management/");
string token = GetCsrfToken(mgntPage);
var nvc = new NameValueCollection()
{
{ "csrftoken", token }
};
http.ApplyConverter<BattleNetBalance>(BattleNetBalance.FromJsonStream);
var balance = http.WebRequest<BattleNetBalance>("https://eu.battle.net/account/data/refresh-balance.html", nvc);
if (balance == null)
throw new Exception("invalid Result");
l.Info("Eur.Balance: {0} Eur.PendingBalance: {1}.", balance.Eur.Balance, balance.Eur.PendingBalance);
Über Feedback würd ich mich freuen, ansonsten, viel Spaß damit.






