【问题标题】:WCF service, response in SOAP or plain XML, how?WCF 服务,SOAP 或纯 XML 中的响应,如何?
【发布时间】:2009-09-29 09:10:42
【问题描述】:

我为此苦苦挣扎了几个小时,但找不到解决沟通问题的方法。 我的服务需要通过 SOAP 或纯 XML 与客户端通信

我的服务将基于 WCF 框架编写,但我的客户不是。

您能否逐步向我展示如何更改我的服务代码和配置以使其返回 SOAP 或 XML 消息?我对这两种解决方案都感兴趣。

我试图根据这个答案来实现这一目标:

REST / SOAP endpoints for a WCF service Call WCF Using SOAP call

但是这个解决方案对我来说都没有正常工作。要么是我的浏览器没有任何内容,要么是找不到资源的错误。

所以我开始了一个新的 WCF 服务项目。它在http://localhost:3151/ 下运行,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfService1
{
    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in Web.config and in the associated .svc file.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

可能我需要创建两个端点?它们都应该包含basicHttpBinding 作为绑定参数。但是还有什么?

另外,如何生成这样的 XML(基于数据契约):

<CompositeType BoolValue = 0 StringValue = "">

而不是这样:

<CompositeType>
  <BoolValue>0</BoolValue>
  <StringValue></StringValue>
</CompositeType>

请注意,我需要双向通信,因此我的服务需要接收 SOAP 或 XML 并以 SOAP 或 XML 响应。

如果可能的话,我希望在浏览器中看到服务方法的描述,就像在 ASP .NET 中一样。

提前感谢您的宝贵时间。

这里有非常大的更新

我试图找到一些解决方案,这就是我迄今为止收集到的全部内容。我只关注纯 XML。

假设协议如下所示:

来自客户的消息:

<MESSAGE MessageParam1 = 0>
  <AdditionalInfo>Some message info </AdditionalInfo>
</MESSAGE>

回复:

<RESPONSE ResponseParam1 = 0>
  <AdditionalInfo>Some response info</AdditionalInfo>
</MESSAGE>

首先,我想查看当前服务方法的描述,并以确切的格式进行参数化,因为它们将被发送/接收。我的意思是,当我在浏览器中调用 Service(刚刚启动服务)时尝试使用 ASP .NET 2.0 WebServices 时,我得到了这样的响应:

POST /Service1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/ShowUser"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ShowUser xmlns="http://tempuri.org/">
      <MyLogin>
        <User>string</User>
        <Password>string</Password>
        <Database>string</Database>
      </MyLogin>
    </ShowUser>
  </soap:Body>
</soap:Envelope>

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ShowUserResponse xmlns="http://tempuri.org/">
      <ShowUserResult>string</ShowUserResult>
    </ShowUserResponse>
  </soap:Body>
</soap:Envelope>

这很棒。除此之外,它具有 SOAP 信封(基础数据也不同),但重点是我可以将其展示给客户并告诉他:“您正在使用这种 XML 结构执行 HTTP POST 方法,并且您正在收到这样的答案”。我想要与 WCF 类似的结果,但更简单 - 没有 SOAP。到目前为止,当我单击 Service1.svc 时,我得到了一堆我不想要的 WSDL 代码。我知道这在某些情况下很好,但我不知道哪个平台正在使用我的客户端。如果他不使用 .NET,那么它可能不会正确导入 WSDL。

所以你知道我想要什么。

这是我在漫长的两天后所做的……:

namespace RESTService
{
    // NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in Web.config.

    [ServiceContract]
    [XmlSerializerFormat]
    public interface IService
    {
        [OperationContract]
        [WebGet]
        Response EchoWithGet(string s);

        [OperationContract]
        [WebInvoke]
        Response EchoWithPost(string s);
    }

    public class Response
    {
        [XmlAttribute]
        public int ResponseParam1;
        [XmlElement]
        public string AdditionalInfo;
    }
}

如您所见,我没有提供 Message 类,因为我不知道如何通过浏览器将它传递给方法。我只知道如何传递一个字符串。

这是实现和配置:

namespace RESTService
{
    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in Web.config and in the associated .svc file.
    public class Service1 : IService
    {
        public Response EchoWithGet(string s)
        {
            Response Transaction;
            Transaction = new Response();
            Transaction.AdditionalInfo = "I've responded: " + s;
            return Transaction;
        }
        public Response EchoWithPost(string s)
        {
            Response Transaction;
            Transaction = new Response();
            Transaction.AdditionalInfo = "I've responded: " + s;
            return Transaction;
        }
    }
}

配置对我来说也有点神秘。我尝试创建绑定,正如 MSDN 的主题之一所述:http://msdn.microsoft.com/en-us/library/aa395208.aspx

但是在调用一个方法后,我返回了一个类似 SOAP 的错误结构,但没有 SOAP 信封。

反正这里是配置:

<system.serviceModel>
      <services>
         <service name="RESTService.Service1">
           <host>
           </host>
           <endpoint 
               address="rest" behaviorConfiguration="webBehavior"
               bindingConfiguration="" binding="webHttpBinding" 
               contract="RESTService.IService"/>
         </service>
       </services>
       <behaviors>
         <endpointBehaviors>
            <behavior name="webBehavior">
               <webHttp />
            </behavior>
         </endpointBehaviors>
       </behaviors>
</system.serviceModel>

当我像这样在浏览器中调用服务方法时:

http://localhost:2443/Service1.svc/rest/EchoWithGet?s=test

我在浏览器中获得了一个 XML 文件:

<Response ResponseParam1="0">
<AdditionalInfo>I've responded: test</AdditionalInfo>
</Response>

看来我走在正确的轨道上?但是,我仍然不知道如何接收有关已发送内容和已接收内容的完整信息(如 ASP .NET 2.0 中的信息)。我宁愿不使用嗅探器侦听服务端口来查看通过 HTTP 的情况。我想看看。另外,当我查看接收到的 XML 的源文件时,我看到:

<?xml version="1.0" encoding="utf-8"?><Response ResponseParam1="0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <br/>
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><br/>
<AdditionalInfo>I've responded: test</AdditionalInfo></Response>

我不想在返回的 XML 中包含这些附加信息,如何删除?

另一个问题是第二种方法:

http://localhost:2443/Service1.svc/rest/EchoWithPost?s=test

这没有按预期工作。我收到“不允许使用方法”的错误消息。如何解决?

所以,让我们总结一下这个长长的问题。

我有一些半途而废的解决方案,可能是正确的方式,也可能是错误的方式。我想请您完成它,它也可以:

  1. 在方法中接受 XML 文件作为参数。
  2. 向我展示如何在 Web 浏览器中以 XML 作为参数调用该方法。是的,我不想在 .NET 中使用单独的客户端。让浏览器成为客户端。
  3. 告诉我如何在返回的 XML 中删除不必要的臃肿信息。
  4. 告诉我如何获取我的服务的类似 .NET 2.0 的描述,同时记住我不想使用 SOAP。
  5. 解释一下 EchoWithPost 方法有什么问题。为什么它不起作用?

如果我的例子不好,请提供一些基本的例子应该如何实现。

我只是在学习 .NET 和 WCF,我很困惑。只有设置正确的数据交换协议才能解决所有这些问题......而且我什至还没有开始编写真正的服务:|

非常感谢您的时间和任何未来的帮助。

【问题讨论】:

  • @wozdu:你完全在正确的轨道上;使用 WCF REST 服务观看有关“Plain Old XML”的截屏视频 - 它允许您做所有您想做的事情(返回完全自定义的 XML,只包含您想要的元素和属性)。

标签: xml wcf web-services soap


【解决方案1】:

您在此处拥有的服务返回一个 SOAP 消息 - 其中将包含“CompositeType”作为其“有效负载”。

WCF 默认使用 SOAP - 任何 basicHttpBinding、wsHttpBinding、netTcpBinding 等都以 SOAP 为基础。

如果您想直接返回 XML,您需要查看 WCF 的 REST 功能 - 这适用于 webHttpBinding(并且仅适用于该绑定)。

另外,如何生成这样的 XML(基于数据契约):

<CompositeType BoolValue = 0 StringValue = "">

而不是这样:

<CompositeType>
  <BoolValue>0</BoolValue>
  <StringValue></StringValue>
</CompositeType>

这是 WCF DataContract 序列化程序的限制。出于性能原因,它不支持属性,例如你不能创建你想要的第一个 XML 片段。

如果您绝对必须拥有第一个 XML,则需要改用 XmlSerializer(它有自己的一组限制/问题)。

马克

更新:如果您只想返回给定的 XML,那么您可能最好使用 REST 方法。

查看 Pluralsight 网站以获取出色的 series of screencasts on using REST,尤其是有关如何创建 plain-old XML (POX) REST service 的截屏视频。

【讨论】:

  • 感谢 marc_s 但如何将 REST 与 XMLSerializer 一起使用?你是说要完成这个简单的任务,我必须放弃合同?这可能吗?
  • 不 - 您仍然可以使用合同,但使用 XML 序列化器而不是 DataContractSerializer,如果您真的必须具有您正在寻找的格式。但这仍然是一个 SOAP 响应。
  • marc_s:谢谢。该规范没有提到任何关于 SOAP 的内容。所以我想我只需要发送和接收一个没有任何信封的 XML。正如我在问题中所展示的那样,此 XML 需要具有属性。我可以请你告诉我如何使用 XMLSerializer 吗?这是我花在寻找答案的第 5 个小时,我很沮丧;)
  • 三思而后行:你是说我不能使用 SOAP 发送一个简单的 XML 属性吗?
  • @wodzu:不,你绝对可以——如果你使用的是 REST 方法,那么如何定义返回的响应完全取决于你
【解决方案2】:

看看Enunciate。我以前用它来创建一个 REST (XML && JSON) 接口以及一个 SOAP 接口。它可能会为您提供您正在寻找的东西,并且非常容易使用。首席开发人员在邮件列表中也非常活跃,因此如果您有任何问题,只需向小组发送消息,您通常会很快得到回复。

【讨论】:

  • 谢谢 Randyaa,会注意的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-17
  • 2014-01-13
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多