9

Silverlight-Windows Phone 7 プロジェクトでは、HttpWebRequest を作成し、RequestStream を取得し、ストリームに何かを書き込んで応答を取得しようとしていますが、常に 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;
}

}

このコードの何が問題なのか誰か知っていますか?

4

4 に答える 4

22

への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 サーバーからの応答を取得しようとする前に、ストリームが閉じていることを確認します。

于 2011-11-21T07:12:46.477 に答える
3

問題は、からのコールバックで元のリクエストにアクセスする方法にありますBeginGetResponse

状態の参照を保持するのではなく、元のリクエストへの参照を取得します。

var request = (HttpWebRequest)asynchronousResult.AsyncState;

電子メールとパスワードの資格情報を Web サイトに投稿することによってログインを実装する、この非常に基本的な (しかし機能する) 例を見てください。

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
            }
        }
    }
}
于 2010-11-12T16:11:03.703 に答える
1

NotSupportedExceptionstring urlが長すぎる場合にも投げることができます。投稿本文の代わりにURLに投稿データをめちゃくちゃにして添付しました。データが短いときは問題なく動作しましたが、データが大きくなりすぎるとEndGetResponseクラッシュしました。

于 2013-01-18T21:16:05.953 に答える
-1

これを変える:

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

これに:

    state.Request.BeginGetResponse(BeginResponse, state);
于 2011-11-13T05:08:23.083 に答える