2

我有以下方法,它基本上是使用他们的 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一条消息,指出流不可读。有了这条线,它告诉我我无法操纵已经关闭的流。这条流是如何关闭的?为什么我不能从中读取?

4

3 回答 3

5

您可以阅读响应的正文。我在这个答案中找到了解决方案。

您应该将流转换为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;
}
于 2015-02-24T20:36:28.347 回答
3

看起来您正在使用 DotNetOpenAuth。不幸的是,我认为这个库在将 WebException 的响应流包装到您的代码收到的 ProtocolException 之前关闭它。您可以在 DEBUG 级别启用日志记录以将响应转储到日志文件中,但我认为您不会找到任何方法从您的代码中访问它。

DotNetOpenAuth 开发人员之一描述了这里的情况:

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

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

于 2013-08-15T17:26:36.663 回答
0

WebException 可能有不同的原因,并且服务器并不总是需要在某些(错误)情况下返回正文,因此没有 response.stream。

先看看返回的状态码

Fiddler是另一个帮助您调查情况的工具

于 2013-03-16T18:54:00.300 回答