HttpWebRequest适当的异常处理

4

我正在使用System.Net程序集中的HttpWebRequest API,但由于C#没有检查异常,我不确定应该在哪里放置try-catch块来正确处理由常见问题(如网络错误)引起的必然异常。在Java中,我们将这些称为普通的已检查IOExceptions。

以下是我的尝试。我的try-catch块是否正确设置以处理网络错误?我是否包装了正确的方法调用?根据文档,我认为它们是正确的,但我需要第二个人审查。

HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "POST";
request.BeginGetRequestStream(getRequestResult =>
            {
                HttpWebRequest getRequestRequest = (HttpWebRequest) getRequestResult.AsyncState;
                try
                {
                    Stream requestStream = getRequestRequest.EndGetRequestStream(getRequestResult);
                    requestStream.Write(parametersData, 0, parametersData.Length);
                    requestStream.Dispose();
                    getRequestRequest.BeginGetResponse(getResponseResult =>
                        {
                            HttpWebRequest getResponseRequest = (HttpWebRequest)getResponseResult.AsyncState;
                            try
                            {
                                WebResponse response = getResponseRequest.EndGetResponse(getRequestResult);
                                Stream responseStream = response.GetResponseStream();
                                StreamReader reader = new StreamReader(responseStream);
                                string jsonString = reader.ReadToEnd();
                                reader.Dispose();
                                JObject jsonObject = JObject.Parse(jsonString);
                                onResult(StatusCode.Ok, jsonObject);
                            }
                            catch (WebException)
                            {
                                onResult(StatusCode.NetworkError);
                            }
                        }, getRequestRequest);
                }
                catch (IOException)
                {
                    onResult(StatusCode.NetworkError);
                }
            }, request);

对于异常处理来说,这看起来对我来说是正确的。顺便提一下,你在输入 Dispose 时应该总是使用 using。所以你应该对 responseStreamreader 进行 using,而不是手动调用 Dispose() - Jan Dörrenhaus
我知道using语句,但因为这里已经有足够的开放和关闭括号了,所以我决定暂时跳过它。使用Dispose()代替using语句是否存在风险? - AxiomaticNexus
1
使用 using 可以打开自己的作用域,在该作用域内才能使用相关变量。如果您手动调用 Dispose,则可以随后再次使用该变量。简而言之,如果正确使用,初始化变量,然后调用 Dispose 并且不再使用它,就像使用 using 一样好。但是,相比之下,using 对人为错误的容忍度更小。 - Jan Dörrenhaus
明白了,谢谢你的提示。 - AxiomaticNexus
1个回答

1
首先,除非你有使用HttpWebRequest的特殊原因,否则最好使用WebClient.UploadString或任何其他WebClient的UploadXXX重载来上传名称/值对、文件、二进制数据等。这会更容易,也更容易排除故障和调试。另外,另一个问题是你将JSON解析期间或在onResult处理程序出错期间的异常视为网络错误。
以下是三个使用WebClient的示例,你可能想尝试同步版本、旧式异步版本和使用async/await的新式异步版本。所有三个版本都尝试解决我上面提到的异常处理问题。如果不需要异步支持,则第一个版本最容易。
static void PostSync (string url, string parametersData)
{
    using (WebClient wc = new WebClient())
    {
        wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; // or "application/json" or ...
        try
        {
            string htmlResult = wc.UploadString(url, parametersData);  // or UploadValues, UploadFile, ... 
            JObject jsonObject = null;
            try
            {
                jsonObject = JObject.Parse(htmlResult);
            }
            catch (JsonException ex)
            {
                onResult(StatusCode.JsonError);
            }
            onResult(StatusCode.Ok, jsonObject);

        }
        catch (System.Net.WebException ex)
        {
            onResult(StatusCode.NetworkError);
        }
    }
}

static void PostAsync(string url, string parametersData)
{
    using (WebClient wc = new WebClient())
    {
        wc.UploadStringCompleted += (Object sender, UploadStringCompletedEventArgs e) =>
        {
            if (e.Error != null)
                onResult(StatusCode.NetworkError);
            JObject jsonObject = null;
            try
            {
                jsonObject = JObject.Parse(e.Result);
            }
            catch (JsonException ex)
            {
                onResult(StatusCode.JsonError);
            }
            onResult(StatusCode.Ok, jsonObject);
        };
        try
        {
            wc.UploadStringAsync(new Uri(url, UriKind.Absolute), parametersData);
        }
        catch (System.Net.WebException ex)
        {
            onResult(StatusCode.NetworkError);
        }
    }
}

static async void PostTaskAsync(string url, string parametersData)
{
    using (WebClient wc = new WebClient())
    {
        wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; // or "application/json" or ...
        try
        {
            string htmlResult = await wc.UploadStringTaskAsync(url, parametersData);  // or UploadValues, UploadFile, ... 
            JObject jsonObject = null;
            try
            {
                jsonObject = JObject.Parse(htmlResult);
            }
            catch (JsonException ex)
            {
                onResult(StatusCode.JsonError);
            }
            onResult(StatusCode.Ok, jsonObject);

        }
        catch (System.Net.WebException ex)
        {
            onResult(StatusCode.NetworkError);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接