如何通过post发送xml到wcf服务

问题描述 投票:0回答:1

我得到了一个将 xml 发布到 wcf 服务的代码。这是完整的代码

1) WCF 服务接口

[OperationContract]
[WebInvoke(Method = "POST",
    UriTemplate = "GetData",
    RequestFormat = WebMessageFormat.Xml,
    BodyStyle = WebMessageBodyStyle.Bare)]
string GetData(DataRequest parameter);

2) WCF 服务实现

public string GetData(DataRequest parameter)
{
    //Do stuff
    return "your data here";
}

3) WCF 服务中的数据契约(在本例中为 DataRequest)

[DataContract(Namespace = "YourNamespaceHere")]
public class DataRequest
{
    [DataMember]
    public string ID{ get; set; }
    [DataMember]
    public string Data{ get; set; }
}

4)发送数据的客户端必须正确构造数据! (本例中为 C# 控制台应用程序)

static void Main(string[] args)
{
    ASCIIEncoding encoding = new ASCIIEncoding();
    string SampleXml = "<DataRequest xmlns=\"YourNamespaceHere\">" +
                                    "<ID>" +
                                    yourIDVariable +
                                    "</ID>" +
                                    "<Data>" +
                                    yourDataVariable +
                                    "</Data>" +
                                "</DataRequest>";

    string postData = SampleXml.ToString();
    byte[] data = encoding.GetBytes(postData);

    string url = "http://localhost:62810/MyService.svc/GetData";

    string strResult = string.Empty;

    // declare httpwebrequet wrt url defined above
    HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
    // set method as post
    webrequest.Method = "POST";
    // set content type
    webrequest.ContentType = "application/xml";
    // set content length
    webrequest.ContentLength = data.Length;
    // get stream data out of webrequest object
    Stream newStream = webrequest.GetRequestStream();
    newStream.Write(data, 0, data.Length);
    newStream.Close();

    //Gets the response
    WebResponse response = webrequest.GetResponse();
    //Writes the Response
    Stream responseStream = response.GetResponseStream();

    StreamReader sr = new StreamReader(responseStream);
    string s = sr.ReadToEnd();

    return s;
}

我的问题是,如果 GetData() 函数需要两个或更多参数,那么我如何为 GetData() 提供值

public string GetData(string xml1,string xml2)
{
     //Do stuff return "your data here";
}

所以请指导我如何将两个 xml 数据传递给

GetData()
函数?

c# xml wcf
1个回答
0
投票

首先,你不能拥有带有

WebMessageBodyStyle.Bare
的服务和带有两个参数的方法。您至少需要更改为
WrappedRequest

[OperationContract]
[WebInvoke(Method = "POST",
     UriTemplate = "GetData",
     RequestFormat = WebMessageFormat.Xml,
     BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetData(DataRequest xml1, string xml2);

让我们看看这个

webHttp
绑定需要什么有线格式。

根元素需要命名为操作的名称,

GetData
。接下来是一系列子元素,每个参数一个。这些元素的默认名称等于变量的名称,因此在示例中它将是
xml1
xml2
。这些默认值可以通过使用
[MessageParameter(Name="Bar")]
属性修饰参数来影响。

应用上述规则将要求您的 HTTP Post 正文看起来与此类似:

<GetData>    <!-- Operation -->
    <xml1>   <!-- parameter one -->
    </xml1>
    <xml2>   <!-- parameter two -->
    </xml2>
</GetData>

不幸的是,事实并非如此。该服务及其合同具有命名空间。没有任何装饰,命名空间是丑陋的

http://tempuri.org/
,我在
IService
界面上用

替换了它
 [ServiceContract(Namespace="http://service.stackoverflow.com")]

在第一个示例中,

DataRequest
类型具有命名空间。在我的测试中,我用

装饰了该类型
 [DataContract(Namespace="http://data.stackoverflow.com")]

现在我们需要将这些命名空间(带有命名空间别名)添加到我们的基本 xml 负载中:

<GetData xmlns="http://service.stackoverflow.com"> <!-- Operation with default namespace  -->
    <xml1 xmlns:a="http://data.stackoverflow.com">   <!-- namespace on type -->
      <a:ID>42</a:ID> <!-- members are in the type namespace, use the alias --> 
      <a:Data>FuBar</a:Data> 
    </xml1>
    <xml2>   <!-- parameter two, no explicit namespace so is in the default one -->
       BlahBlah
    </xml2>
</GetData>

将该有效负载发布到

Service1.svc/GetData
处的服务确实会使用具有反序列化数据的参数调用该服务。

根据您在服务中的示例代码更改准确回答您的问题:

[ServiceContract(Namespace="http://service.stackoverflow.com")]
public interface IService1
{
    [OperationContract]
    [WebInvoke(Method = "POST",
      UriTemplate = "GetData",
        RequestFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    string GetData([MessageParameter(Name="Bar")] DataRequest xml1, string xml2);
}

在客户端:

var yourIDVariable = "foo";
var yourDataVariable = "bar";
string SampleXml = "<xml1 xmlns:a=\"http://data.stackoverflow.com\">" +
                                "<a:ID>" +
                                yourIDVariable +
                                "</a:ID>" +
                                "<a:Data>" +
                                yourDataVariable +
                                "</a:Data>" +
                            "</xml1>";

string xml2 = "some data";
string wrapper = "<GetData xmlns=\"http://service.stackoverflow.com\">{0}<xml2>{1}</xml2></GetData>";
string postData = String.Format(wrapper, SampleXml, xml2);

在处理 WCF 服务调用和诊断序列化问题时,在

system.serviceModel
的配置中启用 WCF 消息日志记录非常方便:

<diagnostics>
  <endToEndTracing activityTracing="true" messageFlowTracing="true" propagateActivity="true"/>
  <messageLogging
     logKnownPii="true"
     logEntireMessage="true" 
     logMalformedMessages="true"
     logMessagesAtServiceLevel="true" 
     logMessagesAtTransportLevel="true"
     maxMessagesToLog="30000"
     maxSizeOfMessageToLog="20000"/>
</diagnostics> 

以及合适的听众:

<system.diagnostics>
   <sources>
     <source name="System.ServiceModel.MessageLogging">
       <listeners>
             <add name="messages"
             type="System.Diagnostics.XmlWriterTraceListener"
             initializeData="messages.svclog" />
        </listeners>
     </source>
  </sources>
  <trace autoflush="true"></trace>
</system.diagnostics>

这为您提供了 Service Trace Viewer 中的确切有效负载:

© www.soinside.com 2019 - 2024. All rights reserved.