【问题标题】:HttpWebRequest.EndGetResponse throws a NotSupportedException in Windows Phone 7HttpWebRequest.EndGetResponse 在 Windows Phone 7 中引发 NotSupportedException
【发布时间】:2011-05-09 03:35:40
【问题描述】:

在 Silverlight-Windows Phone 7 项目中,我正在创建一个 HttpWebRequest,获取 RequestStream,向 Stream 中写入一些内容并尝试获取响应,但我总是得到 NotSupportedException: “System.Net.Browser.OHWRAsyncResult.AsyncWaitHandle 引发了类型为‘System.NotSupportedException’的异常

我的生产代码要复杂得多,但我可以将其缩小到这一小段代码:

public class HttpUploadHelper
{
    private HttpWebRequest request;
    private RequestState state = new RequestState();

    public HttpUploadHelper(string url)
    {
        this.request = WebRequest.Create(url) as HttpWebRequest;
        state.Request = request;
    }

    public void Execute()
    {
        request.Method = "POST";
        this.request.BeginGetRequestStream(
            new AsyncCallback(BeginRequest), state);
    }

    private void BeginRequest(IAsyncResult ar)
    {
        Stream stream = state.Request.EndGetRequestStream(ar);
        state.Request.BeginGetResponse(
            new AsyncCallback(BeginResponse), state);
    }

    private void BeginResponse(IAsyncResult ar)
    {
        // BOOM: NotSupportedException was unhandled; 
        // {System.Net.Browser.OHWRAsyncResult}
        // AsyncWaitHandle = 'ar.AsyncWaitHandle' threw an 
        // exception of type 'System.NotSupportedException'
        HttpWebResponse response = state.Request.EndGetResponse(ar) as HttpWebResponse;
        Debug.WriteLine(response.StatusCode);
    }
}

public class RequestState
{
    public WebRequest Request;
}

}

有人知道这段代码有什么问题吗?

【问题讨论】:

    标签: silverlight httpwebrequest windows-phone-7 iasyncresult


    【解决方案1】:

    问题在于您如何处理访问来自BeginGetResponse 的回调中的原始请求。

    与其持有对状态的引用,不如通过以下方式获取对原始请求的引用:

    var request = (HttpWebRequest)asynchronousResult.AsyncState;
    

    看看这个通过将电子邮件和密码凭据发布到网站来实现登录的非常基本(但有效)的示例。

    public static string Email;
    
    public static string Password;
    
    
    private void LoginClick(object sender, RoutedEventArgs e)
    {
        Email = enteredEmailAddress.Text.Trim().ToLower();
    
        Password = enteredPassword.Password;
    
        var request = (HttpWebRequest)WebRequest.Create(App.Config.ServerUris.Login);
    
        request.ContentType = "application/x-www-form-urlencoded";
        request.Method = "POST";
        request.BeginGetRequestStream(ReadCallback, request);
    }
    
    private void ReadCallback(IAsyncResult asynchronousResult)
    {
        var request = (HttpWebRequest)asynchronousResult.AsyncState;
    
        using (var postStream = request.EndGetRequestStream(asynchronousResult))
        {
            using (var memStream = new MemoryStream())
            {
                var content = string.Format("Password={0}&Email={1}",
                                            HttpUtility.UrlEncode(Password), 
                                            HttpUtility.UrlEncode(Email));
    
                var bytes = System.Text.Encoding.UTF8.GetBytes(content);
    
                memStream.Write(bytes, 0, bytes.Length);
    
                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
    
                postStream.Write(tempBuffer, 0, tempBuffer.Length);
            }
        }
    
        request.BeginGetResponse(ResponseCallback, request);
    }
    
    private void ResponseCallback(IAsyncResult asynchronousResult)
    {
        var request = (HttpWebRequest)asynchronousResult.AsyncState;
    
        using (var resp = (HttpWebResponse)request.EndGetResponse(asynchronousResult))
        {
            using (var streamResponse = resp.GetResponseStream())
            {
                using (var streamRead = new StreamReader(streamResponse))
                {
                    string responseString = streamRead.ReadToEnd();
    
                    // do something with responseString to check if login was successful
                }
            }
        }
    }
    

    【讨论】:

    【解决方案2】:

    改变这个:

        state.Request.BeginGetResponse(
            new AsyncCallback(BeginResponse), state);
    

    到这里:

        state.Request.BeginGetResponse(BeginResponse, state);
    

    【讨论】:

    • 不,"new AsyncCallback()" 在这种情况下什么都不做,一般可以省略。
    【解决方案3】:

    NotSupportedException 可以在调用 EndGetResponse 之前未关闭请求流时抛出。当您尝试获取响应时,WebRequest 流仍处于打开状态并向服务器发送数据。由于流实现了IDisposable 接口,一个简单的解决方案是使用请求流将代码包装在using 块中:

    private void BeginRequest(IAsyncResult ar)
    {
        using (Stream stream = request.EndGetRequestStream(ar))
        {
            //write to stream in here.
        }
        state.Request.BeginGetResponse(
            new AsyncCallback(BeginResponse), state);
    }
    

    using 块将确保在您尝试从 Web 服务器获取响应之前关闭流。

    【讨论】:

      【解决方案4】:

      NotSupportedException 也可以在string url 太长时抛出。我搞砸了并将帖子数据附加到网址而不是帖子正文。当数据很短时,它工作得很好,但一旦它变得太大 - EndGetResponse 崩溃了。

      【讨论】:

        猜你喜欢
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多