为了与REST服务对话,我创建了自己的实现(非常直截了当)。GET请求的代码可以在下面找到。但是,我想知道我的代码中是否存在一些明显的缺陷,使得请求执行起来比它们更糟。他们目前工作体面,但我有一种感觉,我可以做得更好。
如有任何反馈,将不胜感激!
public static void Get<T>(string url, Action<Result<T>> callback, NetworkCredential credentials = null, JsonConverter converter = null)
{
// Checks for no internet
if (!NetworkInterface.GetIsNetworkAvailable())
{
callback(new Result<T>(new NoInternetException()));
return;
}
// Sets up the web request for the given URL (REST-call)
var webRequest = WebRequest.Create(url) as HttpWebRequest;
// Makes sure we'll accept gzip encoded responses
webRequest.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";
// If any credentials were sent, attach them to request
webRequest.Credentials = credentials;
// Queues things up in a thread pool
ThreadPool.QueueUserWorkItem((object ignore) =>
{
// Starts receiving the response
webRequest.BeginGetCompressedResponse(responseResult =>
{
try
{
// Fetches the response
var response = (HttpWebResponse)webRequest.EndGetResponse(responseResult);
// If there _is_ a response, convert the JSON
if (response != null)
{
// Gives us a standard variable to put stuff into
var result = default(T);
// Creates the settings-object to insert all custom converters into
var settings = new JsonSerializerSettings();
// Inserts the relevant converters
if (converter != null)
{
if (converter is JsonMovieConverter)
{
settings.Converters.Add(new JsonMovieListConverter());
}
settings.Converters.Add(converter);
}
// Depending on whether or not something is encoded as GZIP - deserialize from JSON in the correct way
if (response.Headers[HttpRequestHeader.ContentEncoding] == "gzip")
{
var gzipStream = response.GetCompressedResponseStream();
result = JsonConvert.DeserializeObject<T>(new StreamReader(gzipStream).ReadToEnd(), settings);
}
else
{
result = JsonConvert.DeserializeObject<T>(new StreamReader(response.GetResponseStream()).ReadToEnd(), settings);
}
// Close the response
response.Close();
// Launch callback
callback(new Result<T>(result));
}
}
catch (Exception ex) // Deals with errors
{
if (ex is WebException && ((WebException)ex).Response != null && ((HttpWebResponse)((WebException)ex).Response).StatusCode == HttpStatusCode.Unauthorized)
{
callback(new Result<T>(new UnauthorizedException()));
}
else
{
callback(new Result<T>(ex));
}
}
}, webRequest);
});
}一般来说,这段代码应该很清楚,但是下面还有几个事实:
GetCompressedResponse()方法(基本上与原始方法相同)。发布于 2012-08-14 11:37:21
我不知道JSON.net,但是是否有一种形式需要流或流读取器,而不是强迫您先将整个字符串读入内存?如果溪流可能很大,那是相当浪费的,尽管如果它们都很小,也不会有什么区别。
从2.0开始就有一个HttpWebrequest.AutomaticDecompression属性可以简化您的代码(公平地说,我自己总是忘记了这一点)。
您可以使用CachePolicy属性让请求使用IE缓存,如果您将访问相同的URI并由服务器适当地处理它(适当的最大年龄,正确处理条件GET),这将是一个很大的节省。它还允许一些灵活性--例如,如果您的使用对新鲜度有很高的要求,您可以使用Revalidate级别,这样您就可以始终与服务器联系,即使最高年龄表明不应该与服务器联系,但您仍然可以对304进行适当的操作(将其呈现给您的代码,就好像它是200,所以您不需要重写所有内容)。
您甚至可以在此基础上构建一个对象缓存,其中使用IsFromCache方法来了解使用缓存对象是否安全,或者是否需要重新构建它,因为从缓存对象生成的数据已经更改。(实际上,有句著名的话说缓存失效是一个困难的问题,这让我们可以把这个困难的部分推倒到HTTP层,同时让实际缓存的项驻留在.NET层中,而不需要再次反序列化-这是一项有点工作,所以如果由于数据的性质而没有频繁的缓存命中,那么就不要这样做,但是在它工作的地方,它就会发生变化。)
https://stackoverflow.com/questions/11951036
复制相似问题