【问题标题】:SoapException not caught in a ComVisible classSoapException 未在 ComVisible 类中捕获
【发布时间】:2013-01-04 11:15:14
【问题描述】:

我正在.NET 中开发一个 ComVisible 库,然后在旧的 VB6 类中调用它。我在课堂上主要做的是调用 Web 服务、解析响应并返回包含必要数据的对象。 Web 服务被设计为在使用错误参数调用时返回SoapException。这是我的代码的一部分:

    private static WCFPersonClient _client;
    private static ReplyObject _reply;

    public BFRWebServiceconnector()
    {
        _client = new WCFPersonClient("WSHttpBinding_IWCFPerson");
        _reply = new ReplyObject ();            
    }

    [ComVisible(true)]
    public ReplyObject GetFromBFR(string bestallningsID, string personnr, bool reservNummer = false)
    {
        try
        {
            var response = new XmlDocument();

            //the service operation returns XML but the method in the generated service reference returns a string for some reason               
            var responseStr = _client.GetUserData(orderID, personnr, 3); reason.

            response.LoadXml(responseStr);
            //parse the response and fill the reply object
            .......
        }
        catch (Exception ex)
        {
            _reply.Error = "Error: " + ex.Message;
            if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
        }
        return _reply;
    }

一旦我尝试使用正确的参数从我的 VB6 代码中调用此方法,我就会得到正确的回复。但是,如果我用错误的参数调用它,我的 VB6 程序中会出现 -245757 (Object reference was not set to an instance of an object) 运行时错误,而且我的 C# 代码中的 catch 子句似乎没有捕捉到它(虽然我希望空的ReplyObject 填充的Error 字段由方法返回)。

我创建了一个测试 C# 项目并复制了相同的方法(即我从 .NET 平台内调用相同的 Web 服务),我可以确认在这种情况下 SoapException 被正确捕获。

这种行为是故意的吗?有没有办法在 ComVisible 类中捕获SoapException(因为我真的很想将错误消息包含到我的回复对象中)?

UPD:我的 VB6 代码如下:

Set BFRWSCReply = New ReplyObject
Set BFRWSC = New BFRWebbServiceconnector
Set BFRWSCReply = BFRWSC.GetFromBFR(m_BeställningsID, personnr)

If Not IsNull(BFRWSCReply) Then
    If BFRWSCReply.Error= "" Then
       m_sEfternamn = BFRWSCReply.Efternamn
       //etc i.e. copy fields from the ReplyObject
    Else
       MsgBox BFRWSCReply.Error, vbExclamation
    End If
End If

【问题讨论】:

  • 可能 _replay 对象未初始化,而在 catch 子句中设置错误:_reply.Error = "Error: " + ex.Message;
  • @algirdas,不,它是在构造函数中初始化的。
  • VB 的运行时错误是什么?
  • @DStanley 这是-245757 Error 1 - Application-defined or object-defined error : Object reference not set to an instance of an object.
  • ReplyObject 是否也标记为ComVisible

标签: c# interop comvisible soapexception


【解决方案1】:

(这只是一个猜测,更适合评论,但它很长)

BFRWebServiceconnector 类超出范围时,.NET 运行时可能正在处理ReplyObject COM 对象,可能是因为它是类的属性而不是在方法中创建的?

尝试在GetFromBFR 中创建ReplyObject,而不是使其成为类的属性。如果从不同线程调用 COM 对象,这也可以防止多线程访问出现奇怪的错误。

此外,如果 VB 程序中有特定行抛出错误(在您调用 GetFromBFR 之后),您可以查看变量是否在 VB 中为 Nothing 以尝试缩小问题范围。

就像我说的,只是猜测。随意反驳它。 :)

【讨论】:

  • 我会尝试在方法中创建ReplyObject。不知何故,我自己错过了这一点......
【解决方案2】:

我很惭愧,原因很简单……而不是跟随:

catch (Exception ex)
    {
        _reply.Error = "Error: " + ex.Message;
        if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
    }

我实际上有以下代码:

catch (Exception ex)
    {
        _reply.Error = "Error: " + ex.Message + "; " + ex.InnerException.Message;
        if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
    }

原来ex.InnerExceptionnull 导致NullPointerException...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 2021-09-27
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多