简体   繁体   中英

How to send “Raw XML” inside an XML soap message; C#, .Net Web Service

(I'm using a .Net 2.0 Web Service instead of WCF, because my needs are simple and I want full Mono compatibility...)

Ok, I'm a C#/Visual Studio novice, so I apologize for the basic question.

The SOAP service I'm communicating with provides a WSDL, and I used it to create .Net Web Service references. So far, so good.

However, the service expects the payload to be an XML string, like so (an example...)

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <Search xmlns="http://foo.bar/bazservice/">
      <session>ABCDEF0123456789</session>
      <options>

<![CDATA[<Search>
  <SearchConditions>
    <Condition>
      <Field>1234</Field>
      <Value>Test Record</Value>
    </Condition>
  </SearchConditions>
  <Fields>
    <Field>5678</Field>
  </Fields>
</Search>]]>

      </options>
    </Search>
  </soap:Body>
</soap:Envelope>

So I call my function using the generated code that visual studio was nice enough to magic for me, like this:

  // Build an XML thing, and encapsulate it in a CDATA
  XElement searchQuery = this.BuildSearchXml(params, search);
  XCData cdata = new XCData(searchQuery.ToString());

  // XML String looks good...
  Console.WriteLine(cdata.ToString() + Environment.NewLine);

  // Let's send XML payload to service...
  search client = this.Connect("search");

  // Search() expects the second argument to be an XML string...
  var returnVal = client.Search(session, cdata.ToString(), 1);

  return returnVal.ToString();

Unfortunately, the web service glue code, somewhere in the magic that was generated, automatically urlencodes the XML string!

When doing some tcpdump investigation, here's the payload as it's actually sent:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <Search xmlns="http://foo.bar/bazservice/">
      <session>ABCDEF0123456789</session>
      <options>

&lt;![CDATA[&lt;Search&gt;
  &lt;SearchConditions&gt;
    &lt;Condition&gt;
      &lt;Field&gt;1234&lt;/Field&gt;
      &lt;Value&gt;Test Record&lt;/Value&gt;
    &lt;/Condition&gt;
  &lt;/SearchConditions&gt;
  &lt;Fields&gt;
    &lt;Field&gt;5678&lt;/Field&gt;
  &lt;/Fields&gt;
&lt;/Search&gt;]]&gt;

      </options>
    </Search>
  </soap:Body>
</soap:Envelope>

My question is this: how do I keep using the Web Reference magic as it was generated with the WSDL, but tell it to not URLEncode my raw XML string, but send it as is?!

I'm quite the novice - I'm looking at the generated code (in .\\Web References\\MyService\\Reference.cs), but I'm at a loss.

Thanks in advance for any help in pointing me in the right direction!!!

...

edit: added code for Reference.cs

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

//
// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.42000.
//
#pragma warning disable 1591

namespace MyService.Search {
    using System;
    using System.Web.Services;
    using System.Diagnostics;
    using System.Web.Services.Protocols;
    using System.Xml.Serialization;
    using System.ComponentModel;

    // ..... snip other stuff ..... //

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.6.1055.0")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Web.Services.WebServiceBindingAttribute(Name="searchSoap", Namespace="http://foo.bar/bazservice")]
    public partial class search : System.Web.Services.Protocols.SoapHttpClientProtocol {

        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://foo.bar/bazservice/Search", RequestNamespace="http://foo.bar/bazservice", ResponseNamespace="http://foo.bar/bazservice", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        public string ExecuteSearch(string sessionToken, string searchOptions, int pageNumber) {
            object[] results = this.Invoke("Search", new object[] {
                        sessionToken,
                        searchOptions,
                        pageNumber});
            return ((string)(results[0]));
        }

        public void ExecuteSearchAsync(string sessionToken, string searchOptions, int pageNumber) {
            this.ExecuteSearchAsync(sessionToken, searchOptions, pageNumber, null);
        }

        // ..... snip other methods ..... //
    }
}

#pragma warning restore 1591

That's not URL-encoding. That's XML encoding (entity references). It is usually going to be functionally equivalent to the CDATA block. Don't worry about the formatting - it's doing exactly as it should. Just make sure the service is behaving as it should.

https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM