HttpWebRequest.EndGetResponse создает исключение NotSupportedException в Windows Phone 7 - PullRequest
9 голосов
/ 12 ноября 2010

в проекте 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;
}

}

Кто-нибудь знает, что не так с этим кодом?

Ответы [ 4 ]

22 голосов
/ 21 ноября 2011

NotSupportedException может быть выброшено, когда поток запроса не закрыт до вызова EndGetResponse. Поток WebRequest все еще открыт и отправляет данные на сервер, когда вы пытаетесь получить ответ. Поскольку stream реализует интерфейс 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 гарантирует, что поток будет закрыт, прежде чем вы попытаетесь получить ответ от веб-сервера.

3 голосов
/ 12 ноября 2010

Проблема в том, как вы справляетесь с доступом к исходным запросам в обратном вызове от 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
            }
        }
    }
}
1 голос
/ 19 января 2013

NotSupportedException также может быть выброшено, если string url слишком длинный.Я испортил и прикрепил данные поста к URL, а не к телу поста.Когда данные были короткими, они работали просто отлично, но как только они становились слишком большими - EndGetResponse сбой.

0 голосов
/ 13 ноября 2011

Изменить это:

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

На это:

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