[英]Unknown exception when calling a webservice
I have in my system two WCF webservices. 我的系统中有两个WCF Web服务。
The webservice A calls the webservice B. Most part of the time, it works properly. Web服务A调用Web服务B。在大多数情况下,它可以正常工作。 But sometines, an exception in A is raised when it calls B :
但是,有些例程会在A调用B时引发异常:
Exception has been thrown by the target of an invocation.
调用的目标已引发异常。
In order to try to know where is the problem, I put a huge Try Catch in the called method in B, from the first instruction to the last. 为了试图知道问题出在哪里,我从第一个指令到最后一个指令,在B中的被调用方法中放置了一个巨大的Try Catch。 Same problem.
同样的问题。
I try then to put customErrors to off and includeExceptionDetailInFaults to true in order to have details from the exception. 然后,我尝试将customErrors设置为off,将includeExceptionDetailInFaults设置为true,以获取来自异常的详细信息。 Same problem.
同样的问题。
It's not a timeout problem because requests duration are lower than 1 second. 这不是超时问题,因为请求持续时间小于1秒。
I checked length of requests, and some good requests are longer than bad requests. 我检查了请求的长度,一些好的请求比不好的请求要长。 The problem is not the size.
问题不在于大小。
I can't reproduce the problem, because it appears only few times. 我无法重现该问题,因为它只出现了几次。
I think if the problem was on A, exception would have more details than this message. 我认为,如果问题出在A上,则异常将比此消息包含更多详细信息。
Maybe the problem is on IIS (both are on the same IIS instance), but A communicate to B via localhost:xxxx/mywebservice.svc, so It's hard to believe it's a communication problem. 也许问题出在IIS上(两者都在同一个IIS实例上),但是A通过localhost:xxxx / mywebservice.svc与B通信,因此很难相信这是一个通信问题。
EDIT : 编辑:
There is the InnerException Message : 有InnerException消息:
Cannot access a disposed object.
无法访问已处置的对象。 Object name: 'System.ServiceModel.Channels.ServiceChannel'.
对象名称:“ System.ServiceModel.Channels.ServiceChannel”。
The webservice A use a dynamic call for B, using this : http://blogs.msdn.com/b/vipulmodi/archive/2006/11/16/dynamic-programming-with-wcf.aspx Another link here : https://github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/DynamicProxy Web服务A对B使用动态调用,使用的是: http : //blogs.msdn.com/b/vipulmodi/archive/2006/11/16/dynamic-programming-with-wcf.aspx此处的另一个链接: https: //github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/DynamicProxy
Here is my code : 这是我的代码:
DynamicProxy proxy = null;
[...]
proxy = FactoryTest.getProxy(sServiceWsdl, sContract);
[...]
try {
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
proxy.Close();
catch (Exception e)
{
// Here appears the exception
}
[...]
And FactoryTest class : 和FactoryTest类:
public sealed class FactoryTest
{
private static object syncRoot = new Object();
private static Hashtable hashFactory = new Hashtable();
public static DynamicProxy getProxy(String sServiceWsdl, String sContract)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
lock (syncRoot)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
hashFactory.Add(sServiceWsdl, new ProxyTest(sServiceWsdl, sContract));
}
}
}
return ((ProxyTest)hashFactory[sServiceWsdl]).getProxy();
}
public static bool isProxyExists(String sServiceWsdl, String sContract)
{
lock (syncRoot)
{
return hashFactory[sServiceWsdl] == null ? false : true;
}
}
}
There is a complete Exception : 有一个完整的异常:
Exception has been thrown by the target of an invocation.
调用的目标已引发异常。 at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
在System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo方法,对象目标,Object []参数,签名sig,MethodAttributes方法)处的System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo方法,对象目标,Object []参数,SignatureStruct&sig,MethodAttributes methodAttributes,RuntimeType typeOwner)处,位于System.Reflection.RuntimeMethodInfo.Invoke(对象obj,BindingFlags invokeAttr,活页夹活页夹,Object []参数,CultureInfo文化,布尔型skipVisibilityChecks)位于System.Reflection.RuntimeMethodInfo.Invoke(对象obj,BindingFlags invokeAttr,活页夹活页夹) ,Object []参数,CultureInfo文化)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at WS_Generic.Service.CallWsMethod(String sXmlSettings, String sXmlIN, String& sXmlOUT)在WS_Generic.Service.CallWsMethod(String sXmlSettings,字符串sXmlIN, String&sXmlOUT)
There is a complete InnerException : 有完整的InnerException:
Cannot access a disposed object.
无法访问已处置的对象。 Object name: 'System.ServiceModel.Channels.ServiceChannel'.
对象名称:“ System.ServiceModel.Channels.ServiceChannel”。
Server stack trace: at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen() at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
服务器堆栈跟踪:位于System.ServiceModel.Channels.ServiceChannel.Call处System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()处(字符串操作,布尔型单向,ProxyOperationRuntime操作,Object [] ins,Object [] outs,TimeSpan超时) System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage消息)上的System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作)
Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at IWsAfsol.EmvTrxAuthorization(String sXmlIn) at WsAfsolClient.EmvTrxAuthorization(String sXmlIn)
在[0]处抛出异常:在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)在IWsAfsolorization.EmvTr WsAfsolClient.EmvTrxAuthorization(String sXmlIn)处的String sXmlIn)
I did a quick Google with your update and found this post on the asp.net forums. 我对您的更新进行了快速Google搜索,并在asp.net论坛上找到了这篇文章 。
I am guessing (without knowing what your code looks like) that you have a shared connection/service that you leave open and then call whenever you need it in your code. 我猜测(不知道您的代码是什么样)您有一个打开的共享连接/服务,然后在代码中需要它时随时调用。
Options (again, guessing here without seeing code) 选项(再次,在这里猜测而不看代码)
Edit based on your latest edit: 根据您的最新编辑进行编辑:
In your code you are calling proxy.Close(); 在您的代码中,您正在调用proxy.Close();。 which is actually a call to Dispose but you keep the object in your hashtable even though it has been disposed.
这实际上是对Dispose的调用,但是即使对象已被处理,您也将其保留在哈希表中。 Your second call to the same object/service (whenever that occurs) will then trigger your exception.
您对同一对象/服务的第二次调用(无论何时发生)将触发您的异常。 Options are then 1. only call close/dispose when it is no longer needed like when application shuts down or use short lived instances entirely in the context of the calling code ie.
然后,选项为1.仅在不再需要时(例如,应用程序关闭或完全在调用代码的上下文中使用短寿命的实例时),才调用close / dispose。 create, use, destroy and forget for each call and do not persist the instance in your hashlist (you could turn it into a builder to serve a new instance for each request).
为每个调用创建,使用,销毁和忘记,并且不要将该实例保留在哈希列表中(您可以将其变成一个构建器,以为每个请求提供一个新实例)。
Edit #2 based on latest comment 根据最新评论编辑#2
The call to Close still destroys the underlying channels. 调用Close仍会破坏底层通道。 You could test this by calling the same service 2 times in a row and by calling GC.Collect() immediately after your 1st call to Close() like this:
您可以通过连续两次调用同一服务,并在第一次调用Close()之后立即调用GC.Collect()来进行测试,如下所示:
....
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
proxy.Close();
GC.Collect();
var sXmlOUT2 = (String)proxy.CallMethod(sMethod, sXmlIN); // should trigger your exception
...
Here is a way you could refactor your code. 这是一种重构代码的方法。
public class SomeClass
{
FactoryTest factory; // instantiate this somewhere like constructor
public void someMethod()
{
[...]
var proxy = factory.getProxy(sServiceWsdl, sContract);
[...]
try {
sXmlOUT = (String)proxy.CallMethod(sMethod, sXmlIN);
// proxy.Close(); - do not close connection
catch (Exception e)
{
// Here appears the exception
}
}// end method
}// end class
// optionally if you want the same instance to server other callers
// you can turn this into a Singleton pattern and return a shared
// static instance of FactoryTest via a static method. Do not forget to
// dispose of the singleton at the end of your application
public sealed class FactoryTest : IDisposable
{
private object syncRoot = new Object();
private Hashtable hashFactory = new Hashtable();
public DynamicProxy getProxy(String sServiceWsdl, String sContract)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
lock (syncRoot)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
hashFactory.Add(sServiceWsdl, new ProxyTest(sServiceWsdl, sContract));
}
}
}
return ((ProxyTest)hashFactory[sServiceWsdl]).getProxy();
}
public bool isProxyExists(String sServiceWsdl, String sContract)
{
lock (syncRoot)
{
return hashFactory[sServiceWsdl] == null ? false : true;
}
}
public void Dispose()
{
// implement IDisposable
// dispose of everything hashFactory using Close() or Dispose()
}
} // end class
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.