WCF服务,SOAP或纯XML中的响应,如何?

时间:2009-09-29 09:10:42

标签: xml wcf web-services soap

我正在努力工作几个小时,无法找到解决通信问题的方法。 我的服务需要通过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中的信息)。我宁愿不用sniffer监听服务端口来查看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. 演示如何使用XML作为参数在Web浏览器中调用该方法。是的,我不想在.NET中使用单独的客户端。让浏览器成为客户端。
  3. 告诉我如何在返回的XML中删除不必要的膨胀信息。
  4. 告诉我如何获取类似.NET 2.0的服务描述,同时牢记我不想拥有SOAP。
  5. 解释一下EchoWithPost方法有什么问题。为什么它不起作用?
  6. 如果我的例子不好,请向我提供一些基本的例子。

    我只是在学习.NET和WCF而且我很困惑。所有这些问题只有设置正确的数据交换协议......我甚至没有写入真正的服务:|

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

2 个答案:

答案 0 :(得分:7)

您在这里的服务返回一条SOAP消息 - 其中包含“CompositeType”作为其“payload”。

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的截屏视频。

答案 1 :(得分:0)

看看Enunciate。我之前使用它来创建REST(XML&amp;&amp; JSON)接口以及SOAP接口。它可能会给你你正在寻找的东西,它很容易使用。首席开发人员在邮件列表中也非常活跃,所以如果您有任何问题,只需向群组发送消息,您通常会很快收到回复。