读取WebException的响应流

时间:2013-03-16 18:34:41

标签: c# asp.net facebook stream dotnetopenauth

我有以下方法,它基本上使用他们的Facebook凭据验证用户。出于某种原因,我在尝试处理授权密钥(代码)时得到WebException。所以我试着读取响应流以便知道发生了什么,但是在读取流时我一直遇到错误。这是我的代码:

    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);
            }
        }
    }

如果我删除了responseStream.Seek(0, SeekOrigin.Begin);行,则会向我ArgumentException发送一条消息,指出该流不可读。有了这条线,它告诉我,我无法操纵已经关闭的流。这条小溪是怎么关闭的?为什么我不能从中读取?

3 个答案:

答案 0 :(得分:5)

您可以阅读回复的正文。我在this answer找到了解决方案。

您应该将流转换为MemoryStream并使用ToArray方法,然后使用Encoding.UTF8.GetString获取文字。

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;
}

答案 1 :(得分:3)

看起来您正在使用DotNetOpenAuth。不幸的是,我认为这个库在将它包装在你的代码收到的ProtocolException之前关闭了WebException的响应流。您可以在DEBUG级别enable logging将响应转储到日志文件中,但我认为您无法通过代码访问它。

其中一个DotNetOpenAuth开发人员描述了情况here

  

DotNetOpenAuth在处理和抛出包装的异常时关闭HTTP响应流,因为如果DNOA没有关闭流,您的开放流分配将填满,然后您的应用将开始挂起。如果我没记错的话,DNOA会将响应流的内容写入其日志。

最新(未发布)的DNOA(5.0)版本可能已发生变化,因为当前版本中导致问题的部分代码已被删除。

答案 2 :(得分:0)

WebException可能有不同的原因,并且服务器并不总是需要在某些(错误)环境下返回一个主体,因此没有response.stream。

首先查看返回的状态代码

另一个可以帮助您调查目标的工具是Fiddler