简体   繁体   中英

Reading the response stream of a WebException

I have the following method which is basically authenticating users with their Facebook credentials. For some reason, I am getting a WebException when trying to process the authorization key (code). So I tried to read the response stream in order to know what is going on but I keep getting errors while reading the stream. Here's my code:

    private void OnAuthCallback(HttpContextWrapper context, WebServerClient client)
    {
        try
        {
            IAuthorizationState authorizationState = client.ProcessUserAuthorization(context.Request);
            AccessToken accessToken = AccessTokenSerializer.Deserialize(authorizationState.AccessToken);
            String username = accessToken.User;
            context.Items[USERNAME] = username;
        }
        catch (ProtocolException e)
        {
            if (e.InnerException != null)
            {
                String message = e.InnerException.Message;
                if (e.InnerException is WebException)
                {
                    WebException exception = (WebException)e.InnerException;
                    var responseStream = exception.Response.GetResponseStream();
                    responseStream.Seek(0, SeekOrigin.Begin);
                    using (StreamReader sr = new StreamReader(responseStream))
                    {
                        message = sr.ReadToEnd();
                    }
                }
                EventLog.WriteEntry("OAuth Client", message);
            }
        }
    }

If I remove the responseStream.Seek(0, SeekOrigin.Begin); line, it gives me an ArgumentException with a message that says the stream was not readable. And with this line in place, it tells me that I cannot manipulate a stream that was already closed. How was this stream closed? And why can't I read from it?

You can read the body of the response. I've found the solution in this answer .

You should cast the stream to MemoryStream and use ToArray method, then use Encoding.UTF8.GetString to get text.

private void OnAuthCallback(HttpContextWrapper context, WebServerClient client)
{
    try
    {
        IAuthorizationState authorizationState = client.ProcessUserAuthorization(context.Request);
        AccessToken accessToken = AccessTokenSerializer.Deserialize(authorizationState.AccessToken);
        String username = accessToken.User;
        context.Items[USERNAME] = username;
    }
    catch (ProtocolException e)
    {
        if (e.InnerException != null)
        {
            String message = e.InnerException.Message;
            if (e.InnerException is WebException)
            {
                WebException exception = (WebException)e.InnerException;
                message = ExtractResponseString(webException);
            }
            EventLog.WriteEntry("OAuth Client", message);
        }
    }
}

public static string ExtractResponseString(WebException webException)
{
    if (webException == null || webException.Response == null)
        return null;

    var responseStream = 
        webException.Response.GetResponseStream() as MemoryStream;

    if (responseStream == null)
        return null;

    var responseBytes = responseStream.ToArray();
    var responseString = Encoding.UTF8.GetString(responseBytes);
    return responseString;
}

It looks like you are using DotNetOpenAuth. Unfortunately I think this library closes the response stream of the WebException before wrapping it in the ProtocolException that your code receives. You can enable logging at the DEBUG level to have the response dumped to a log file, but I don't think you'll find any way to access it from your code.

One of the DotNetOpenAuth devs describes the situation here :

DotNetOpenAuth closes the HTTP response stream while handling and throwing the wrapped exception because if DNOA didn't close the stream, your open streams allotment would fill up and then your app would start hanging. DNOA does write the response stream's content to its log if I recall correctly.

Things may have changed in the latest (unreleased) version of DNOA (5.0), as the part of the code that is causing the problem in the current release version has been removed.

a WebException can have different causes and the server isn't always required to return a body under certain (error-)circumstance thus no response.stream.

Have a look at the returned status-code first

Another tool to help you investigate what's going is Fiddler

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM