我有一个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
我还应该补充一点,当im调试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
消息=远程服务器返回错误:NotFound。StackTrace:在System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult结果)在System.ServiceModel.Channels.ServiceChannel.EndCall(字符串操作,对象[]输出,IAsyncResult结果)在System.ServiceModel.ClientBase 1.ChannelBase
1.EndInvoke(String methodName,Object[]args,IAsyncResult result)位于MatrixWebMap.AuthServiceRef.AuthServiceClient.AuthServiceClient通道.EndGetToken(IAsyncResult结果)位于MatrixWebMap.AuthServiceRef.AuthServiceClient.AuthServiceRef_AuthService_EndGetToken(IAsyncResult结果)位于MatrixWebMap.AuthServiceRef.AuthServiceClient.OnEndGetToken(IAsyncResult结果)位于System.ServiceModel.ClientBase`1.OnAsyncCallCompleted(IAsyncResult结果)InnerException:System.Net.WebException消息=远程服务器返回错误:NotFound。StackTrace:位于System.Net.Browser.AncHelper.BeginOnUI(SendOrPostCallback beginMethod,对象状态)位于System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult-asyncResult)位于System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChanelAsyncRequest.CompleteGetResponse(IAsyncResult结果)InnerException:System.Net.WebException消息=远程服务器返回错误:NotFound。StackTrace:位于System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult-asyncResult)位于System.Net.Browser.BrowserHttpWebRequest。<>c_DisplayClassa.b_9(对象发送状态)位于System.Net.Browser.AncHelper。<>c_DisplayClass4.b_0(对象发送状态)内部异常:
因此,从我将异常添加到TokenResult类并返回它时收集到的信息来看,WCF响应的异常属性有问题。解决方法是在响应之前处理异常,并使TokenException成为在返回结果之前创建的字符串。
因此,对于一个"403 Forbidden"web异常,我只是构造了一个字符串并返回"您输入的信息与我们的记录不匹配。请再试一次。"这是一项肮脏的工作,但它完全适合我在这里尝试做的事情。
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