1

我正在努力从 webservice/webclient 架构迁移到 WCF 架构。该对象非常复杂,有很多嵌套的 xsd 和不同的命名空间。通过将 Web 引用添加到具有 30 多个 Web 方法的原始 wsdl 并使用 xsd.exe 生成缺少的 SOAPFault 对象来生成代理类。我的试点 WCF 服务仅包含 1 个与原始方法之一的确切语法匹配的 web 方法:1 个对象作为参数,返回 1 个其他对象作为结果值。我使用这些代理类创建了一个 WCF 接口,使用属性:XMLSerializerFormatServiceContract在接口OperationContract上,使用原始 wsdl 指定的一种方法ActionReplyAction,都具有适当的命名空间。我使用 SoapUI 创建传入的客户端消息;我从原始 WSDL 文件生成了一个项目(导致 SoapUI 项目有 30 多个方法),并在一个实现的 WebMethod 上创建了一个新请求,将 URL 更改为我的 wcf Web 服务并发送消息。由于 中指定的 (Reply-)Action OperationContractAttribute,消息实际上被接收并正确反序列化为对象。

为了做到这一点(40 小时的谷歌搜索),很多挫折使我使用了一个自定义端点,在该端点中删除了 WCF“包装标签”,更正了嵌套类型的命名空间,并且生成的 wsdl 得到了展平(为了更好与其他工具的兼容性,然后是 MS VisualStudio)。

接口代码是这样的:

[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document, SupportFaults = true)]
[ServiceContract(Namespace = Constants.NamespaceStufZKN)]
public interface IOntvangAsynchroon
{

    [OperationContract(Action = Constants.NamespaceStufZKN + "/zakLk01", ReplyAction = Constants.NamespaceStufZKN + "/zakLk01", Name = "zakLk01")]
    [FaultContract(typeof(Fo03Bericht), Namespace = Constants.NamespaceStuf)]
    Bv03Bericht zakLk01([XmlElement("zakLk01", Namespace = Constants.NamespaceStufZKN)] ZAKLk01 zakLk011);

当我在代码中使用 Web 客户端发送消息时,一切正常。我的问题是,当我使用 WCF 客户端时。我ChannelFactory<IOntvangAsynchroon>用来发信息。但是生成的 xml 看起来不同:它包含方法的参数名!我花了很多时间来解决这个问题,但这是发生的事情:

正确的 xml(剥离的肥皂信封):

<soap:Body>
  <zakLk01 xmlns="http://www.egem.nl/StUF/sector/zkn/0310">
    <stuurgegevens>
      <berichtcode xmlns="http://www.egem.nl/StUF/StUF0301">Bv01</berichtcode>
      <zender xmlns="http://www.egem.nl/StUF/StUF0301">
        <applicatie>ONBEKEND</applicatie>
      </zender>
    </stuurgegevens>
    <parameters>
    </parameters>
  </zakLk01>
</soap:Body>

错误的xml:

<soap:Body>
  <zakLk01 xmlns="http://www.egem.nl/StUF/sector/zkn/0310">
    <zakLk011>
    <stuurgegevens>
      <berichtcode xmlns="http://www.egem.nl/StUF/StUF0301">Bv01</berichtcode>
        <zender xmlns="http://www.egem.nl/StUF/StUF0301">
          <applicatie>ONBEKEND</applicatie>
        </zender>
      </stuurgegevens>
      <parameters>
      </parameters>
    </zakLk011>
  </zakLk01>
</soap:Body>

注意zakLk011元素?它是我界面中方法的参数名称!所以现在是zakLk011,但是当我的参数名称是时zakLk01,xml 似乎包含上面标记的一些神奇副本,但没有命名空间。当然,你可以想象我在发现它是参数名之前对发生的事情发疯了!

我现在实际上已经创建了一个 WCF 服务,我无法再使用 WCF 客户端发送消息。为清楚起见:该方法确实在我的 Web 服务上使用 WCF 客户端调用,但参数对象为空。因为我使用自定义端点来记录传入的 xml,所以我可以看到消息接收良好,但语法错误!

WCF 客户端代码:

ZAKLk01 stufbericht = MessageFactory.CreateZAKLk01();
ChannelFactory<IOntvangAsynchroon> factory = new ChannelFactory<IOntvangAsynchroon>(new BasicHttpBinding(), new EndpointAddress("http://localhost:8193/Roxit/Link/zkn0310"));
factory.Endpoint.Behaviors.Add(new LinkEndpointBehavior());
IOntvangAsynchroon client = factory.CreateChannel();
client.zakLk01(stufbericht);

我没有使用生成的客户端,我只是像以前那样引用 Web 服务(共享库)。

编辑:生成服务参考时,它会生成重复的类(不知道为什么..)。但是,当删除这些重复项时,客户端会使用正确的 xml 发送消息。但是我的架构需要共享库,所以这对我没有帮助。

谁能帮帮我吗?我无法在此搜索任何内容...

4

2 回答 2

0

好吧,我自己想通了。我已经创建了一个有效的 WCF 客户端(服务参考),通过仔细查看生成的代码,我弄清楚了发生了什么。它与 WCF 包装在 Web 服务方法的声明中使用的所有类的方式有关(因此在方法提到的类的属性中使用的类没有被包装)。在我的例子中,ZAKLk01 类的主体使用 XMLElement 标签包装,使用参数名作为 XMLElement-name。为了摆脱这种行为,我现在为我生成的代理类 ZAKLk01 和 Bv03Bericht 使用包装类,就像在我的新 WCF 客户端中生成的类对我的服务引用代理类所做的那样。这些包装类用 MessageContractAttributes 修饰。

举一个这些包装类之一的例子:

[MessageContract(IsWrapped = false)]
public partial class zakLk01Request
{

    [MessageBodyMember(Namespace = Constants.NamespaceStufZKN, Order = 0)]
    public ZAKLk01 zakLk01;

    public zakLk01Request()
    {
    }

    public zakLk01Request(ZAKLk01 zakLk01)
    {
        this.zakLk01 = zakLk01;
    }
}

我的接口方法现在看起来像这样:

[OperationContract(Action = Constants.NamespaceStufZKN + "/zakLk01", ReplyAction = Constants.NamespaceStufZKN + "/Bv03Bericht")]
[FaultContract(typeof(Fo03Bericht), Namespace = Constants.NamespaceStuf)]
zakLk01Response zakLk01(zakLk01Request zakLk01);

没有 XMLElement 标记,该函数(生成正确的 xml)现在已经被包装类替换了。

我可以收到未包装的 xml 的原因是我的自定义 messageinspector 包含一些代码,旨在接受未包装的 xml 消息,而无需将 MessageContract 标记添加到所有现有类(或创建大量包装器类)(在某处搜索) ,它做得很好。代码片段:

MessageDescription.Body.WrapperName = null;

但是接收由我的(第一个)WCF 客户端发送的仍然包装类的包装消息不起作用,当然......

我仍然不明白的是那些 Action 属性是如何工作的:如果我不提供它们,我生成的 wsdl 不包含任何方法。好吧,现在不重要,因为我终于可以继续前进了,并且会在其他时间修改 Action 属性。

于 2010-06-02T12:54:38.830 回答
0

建议:如果您刚刚开始使用 WCF,请从“WCF 方式”做事开始。一旦你知道如何正确地做到这一点,你就可以开始改变事情了。现在,您不知道您的问题有多少是由于 WCF 造成的,而有多少是由于您缺乏使用 WCF 的经验。

我建议你从头开始,不要使用[XmlSerializerFormat]. 只需创建ServiceContract一个OperationContract. 至少包括一个FaultContract,这样你就可以看到它是如何工作的。

使用“添加服务引用”创建一个 WCF 客户端,并确保它可以正常工作。

然后使用来自 WCF 服务的 WSDL(不是原始 WSDL)创建一个 SOAPUI 项目。确保有效。

然后你就可以开始改变事情了。试试[XmlSerializerFormat]。尝试添加各种[Xml*]属性。慢慢地开始改变事情,直到你看到什么坏了。

于 2010-06-02T06:58:34.547 回答