我已经创建了自己的实现(非常直接),以便与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()
(与原始方法基本相同)。答案 0 :(得分:1)
我不知道JSON.net,但是有一个表单需要流或流读取器,而不是强迫您先将整个字符串读入内存吗?如果流可能很大,这是相当浪费的,但如果它们都很小的话就没有区别。
自2.0以来,有HttpWebrequest.AutomaticDecompression
属性可以简化您的代码(公平地说,我自己总是忘记这一点)。
您可以使用CachePolicy
属性让请求使用IE缓存,如果您使用相同的URI并且服务器正确处理它(适当的max-age,正确处理),这可能是一个很大的节省有条件的GET)。它还允许一些灵活性 - 例如如果您的使用对新鲜度要求很高,您可以使用Revalidate
级别,这样您就可以随时联系服务器,即使max-age表明不应该联系服务器,但您仍然可以使用304适当(呈现给您的代码就好像它是200,所以你不需要重写所有内容)。
您甚至可以在此基础上构建对象缓存,您可以使用IsFromCache
方法知道使用缓存对象是否安全,或者是否因为构建数据而需要重建它来自改变了。 (实际上这真的很好,有一个关于缓存失效的着名线路是一个难题,这让我们将这个硬位的降压传递到HTTP层,同时让实际缓存的项目存在于.NET层中而不是需要再次反序列化 - 这是一些工作,所以如果由于数据的性质而不会频繁出现缓存命中,那么就不要这样做,但它确实有效,它会摇滚)。