0

I have to implement a SOAP 1.1 web service in ASP.NET. I am given request and response examples and a glitchy wsdl spec that, when fed to the wsdl-->code wizard, doesn't produce code that gives correct response. So I am stuck with manual fixing of the auto-generated C# code.

Here is the response one of the methods must produce:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sws="http://something/WebService">
   <soapenv:Header/>
   <soapenv:Body>
      <sws:MyActionResponse>
         <sws:returnVariableOne>?</sws:returnVariableOne>
         <sws:returnVariableTwo>?</sws:returnVariableTwo>
         <sws:returnVariableThree>?</sws:returnVariableThree>
      </sws:MyActionResponse>
   </soapenv:Body>
</soapenv:Envelope>

I can't find a way how to make the <sws:MyActionResponse> contain several elements, in the specified order.

I have this code that produces only one child under the <sws:MyActionResponse> element:

[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://something/WebService/MyAction", RequestElementName="MyActionRequest", RequestNamespace="http://something/WebService", ResponseNamespace="http://something/WebService", ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped, Use=System.Web.Services.Description.SoapBindingUse.Literal)]
[return: System.Xml.Serialization.XmlElementAttribute("returnVariableOne")]
public override string MyAction(string inputVariable)
{
    return "Value of variable #1";
}

The response xml from it looks like this:

<?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>
    <MyActionResponse xmlns="http://something/WebService">
      <returnVariableOne>Value of variable #1</returnVariableOne>
    </MyActionResponse>
  </soap:Body>
</soap:Envelope>

Well, I need three child elements there, so I am looking for the C# syntax that causes the WebMethod to return sequence of several elements in prescribed order. I am aware that I could return one complex element with complex data structures inside it, but that doesn't help because I have to match the xml response sample I am given in the spec.

Passiday
  • 7,573
  • 8
  • 42
  • 61
  • Why not treat the Response itself as a complex type? – Plamen G Apr 19 '15 at 21:46
  • Perhaps, but I am not aware what attributes and syntax should be used to override the SOAP response message element. – Passiday Apr 20 '15 at 08:20
  • I reviewed one of the services I consumed in the past - the definition of a sample response looks like this: http://pastebin.com/iAREa2Bg . Why don't you attach the WSDL to see what's wrong with it and fix it - it might be easier? – Plamen G Apr 20 '15 at 08:32
  • Sorry, can't share the wsdl, it is huge and confidential, as it is related to business app. – Passiday Apr 24 '15 at 19:26
  • I see. No problem, glad you solved it somehow. – Plamen G Apr 24 '15 at 19:27

1 Answers1

1

I have solved this with pretty brutal approach - by editing the output stream. Until I learn of better way.

Put this code in global.asax:

using System.IO;
using System.Text.RegularExpressions;
using System.Text;

public class XmlElementStripper : MemoryStream
{
    private Stream outputStream;
    private Regex reStripper = new Regex(@"</?removeThisTag>", RegexOptions.Compiled | RegexOptions.Multiline);

    public XmlElementStripper(Stream output)
    {
        outputStream = output;
    }
    public override void Write(Byte[] buffer, int offset, int count)
    {
        // Convert the content in buffer to a string
        String contentInBuffer = UTF8Encoding.UTF8.GetString(buffer);
        // Strip out the tags
        contentInBuffer = reStripper.Replace(contentInBuffer, String.Empty);
        // Output the modified string
        outputStream.Write(UTF8Encoding.UTF8.GetBytes(contentInBuffer), offset, UTF8Encoding.UTF8.GetByteCount(contentInBuffer));
    }
}

In Global class (System.Web.HttpApplication):

protected void Application_PostReleaseRequestState(Object sender, EventArgs e)
{
    if (Response.ContentType.StartsWith("text/xml"))
    {
        Response.Filter = new XmlElementStripper (Response.Filter);
    }
}

Now, if the web method has this return attribute

[return: System.Xml.Serialization.XmlElementAttribute("removeThisTag")]

Then the and tags are edited out of the output stream, and when the web method returns complex type consisting of several xml-serialized fields, they are direct children of the main SOAP response message element.

Passiday
  • 7,573
  • 8
  • 42
  • 61