【问题标题】:WCF Service times out if WebClient returns exception如果 WebClient 返回异常,WCF 服务将超时
【发布时间】:2012-02-24 15:58:24
【问题描述】:

我有一个 WCF 服务作为代理,它调用 WebClient 来返回一个字符串。 WebClient 正在查询通过 https 发送用户名和密码的 Token 服务。如果用户名和密码正确,服务可以正常工作,但是如果用户名和密码无效,WebClient 会抛出异常(403 Forbidden),这是预期的并在下面的代码中处理。但是,WCF 服务会继续挂起,直到超时,我不知道为什么。

Public Function GetToken(un As String, pw As String, ref As String) As TokenResult Implements IAGSAuthentication.GetToken

        Dim Token As String
        Dim TokenURL As String = String.Format("https://server/arcgisserver/tokens?request=getToken&username={0}&password={1}&timeout={2}", un, pw, Timeout)
        Dim tokenResult As TokenResult = New TokenResult
        If TokenService.IsBusy = False Then

            Try
                Token = TokenService.DownloadString(New Uri(TokenURL))
                tokenResult.Token = Token
                Return tokenResult
                Exit Function
            Catch ANEx As ArgumentNullException
                TokenService.Dispose()
                tokenResult.TokenException = ANEx
                Return tokenResult
                Exit Function
            Catch WEx As WebException
                TokenService.Dispose()
                tokenResult.TokenException = WEx
                Return tokenResult
                Exit Function
            Catch CEx As CommunicationException
                TokenService.Dispose()
                tokenResult.TokenException = CEx
                Return tokenResult
                Exit Function
            Catch Ex As Exception
                TokenService.Dispose()
                tokenResult.TokenException = Ex
                Return tokenResult
                Exit Function
            End Try

        End If
        Return tokenResult
    End Function

我还应该补充一点,当我调试 WCF 参考文件时,我会在自动填充的客户端方法中显示一个异常。

Public Function EndGetToken(ByVal result As System.IAsyncResult) As AuthServiceRef.TokenResult Implements AuthServiceRef.AuthService.EndGetToken
                Dim _args((0) - 1) As Object
                Dim _result As AuthServiceRef.TokenResult = CType(MyBase.EndInvoke("GetToken", _args, result),AuthServiceRef.TokenResult)
                Return _result
            End Function

我认为,通过在 WCF 服务中处理异常并在自定义类中返回异常,我可以将异常推送给用户,而不会出现运行时问题。这是客户端捕获的异常:

System.ServiceModel.CommunicationException was unhandled by user code

Message=远程服务器返回错误:NotFound。 堆栈跟踪: 在 System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult 结果) 在 System.ServiceModel.Channels.ServiceChannel.EndCall(字符串操作,对象 [] 输出,IAsyncResult 结果) 在 System.ServiceModel.ClientBase1.ChannelBase1.EndInvoke(String methodName, Object[] args, IAsyncResult 结果) 在 MatrixWebMap.AuthServiceRef.AuthServiceClient.AuthServiceClientChannel.EndGetToken(IAsyncResult 结果) 在 MatrixWebMap.AuthServiceRef.AuthServiceClient.AuthServiceRef_AuthService_EndGetToken(IAsyncResult 结果) 在 MatrixWebMap.AuthServiceRef.AuthServiceClient.OnEndGetToken(IAsyncResult 结果) 在 System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult 结果) 内部异常:System.Net.WebException Message=远程服务器返回错误:NotFound。 堆栈跟踪: 在 System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod,对象状态) 在 System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult) 在 System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult 结果) 内部异常:System.Net.WebException Message=远程服务器返回错误:NotFound。 堆栈跟踪: 在 System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult) 在 System.Net.Browser.BrowserHttpWebRequest.c_DisplayClassa.b_9(对象 sendState) 在 System.Net.Browser.AsyncHelper.c_DisplayClass4.b_0(对象 sendState) 内部异常:

【问题讨论】:

  • 可能是因为你dispose了TokenService?
  • 注释掉 dispose 方法并没有改变任何东西。
  • System.ServiceModel.CommunicationException 未被用户代码处理 Message=远程服务器返回错误:未找到。 StackTrace:在 System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result) .....问题是它是在代码中处理的,我在自定义类 TokenResult 中返回异常,所以我不确定异常来自哪里从
  • 所以,我建议您将此信息添加到您的问题中。您现在的问题似乎是“这个 NotFound 异常的故事是什么”
  • 可能是当抛出异常时,一个异常标志的侦听器或类似的东西,WCF 服务遇到的标志导致无法正常工作。当我调试它时,它似乎在返回结果的函数完成时挂起。

标签: wcf silverlight exception-handling webclient


【解决方案1】:

因此,根据我将异常添加到 TokenResult 类并返回它时收集到的信息,WCF 响应的异常属性存在问题。解决方法是在响应之前处理异常,并使 TokenException 成为在返回结果之前创建的字符串。

因此,对于“403 Forbidden”网络异常,我只是构造了一个字符串并返回“”您输入的信息与我们的记录不符。请再试一次。” 有点肮脏的工作,但它完全适合我在这里尝试做的事情。

            Try
                Token = TokenService.DownloadString(New Uri(TokenURL))
                tokenResult.Token = Token
                Return tokenResult
                Exit Function

            Catch ANEx As ArgumentNullException                
                tokenResult.TokenException = ANEx.Message
                Return tokenResult
                Exit Function

            Catch WEx As WebException                   
                If WEx.Status = WebExceptionStatus.ProtocolError Then
                    tokenResult.TokenException = "The information you have entered does not match our records. Please try again."
                Else
                    tokenResult.TokenException = WEx.Message
                End If
                Return tokenResult
                Exit Function

            Catch CEx As CommunicationException      
                tokenResult.TokenException = CEx.Message
                Return tokenResult
                Exit Function

            Catch Ex As Exception                    
                tokenResult.TokenException = Ex.Message
                Return tokenResult
                Exit Function
            End Try

【讨论】:

  • 我认为这是因为 WCF 响应以 xml 格式返回给客户端,并且异常被视为未经处理的异常,因为它作为异常类返回。所以在服务器端处理它并返回一个字符串可能是解决这个问题的好方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多