Client found response content type of '', but expected 'text/xml'

Discussion in 'ASP .Net Web Services' started by hugedifference@gmail.com, Nov 1, 2006.

  1. Guest

    On day 3 of debugging this. I've implemented a simple soap extension
    to intercept the servers outgoing soap message stream and replace it
    with my own (code below).

    Everything seems to work in the code step through except the server
    side afterserialize stage is called twice (2 times!) but why? It
    should only fire once afaik. In the second fire, afterserialize writes
    an empty stream to the output stream, but I already wrote to the output
    stream correctly on the first fire! My client says, expectedly, the
    above error, the service returns nothing==empty stream.

    I've found many hits on the net, but no answers. Day 4 is coming.
    Argggh! The only post I found with an answer was this one:
    http://www.thescripts.com/forum/thread375954.html but I don't think it
    applies in my case as I rewound the stream correctly (or at least I
    think I did).

    I'm using vs 2005 and I'm running on XP pro. I'm using the embedded
    webserver in 2005 (cassini?)

    As I said, everything appears to work fine. On the server side It
    takes the input message, transforms it, and then writes it to the
    output stream. I checked the stream it copies to the output (in
    afterserialize on the first time it fires) and everything looks
    hunky-dory. However, the second time afterserialize fires everything
    is messed up and the streams are empty (appoutputstream and
    httpoutputstream).


    all code below here
    --*********************
    Here is the soap extension
    --**********************

    using System;
    using System.Web;
    using System.Web.Services;
    using System.IO;
    using System.Web.Services.Protocols;
    using System.Xml;

    public class XmlStreamSoapExtension :
    System.Web.Services.Protocols.SoapExtension
    {
    bool output = false;
    Stream httpOutputStream;
    Stream chainedOutputStream;
    Stream appOutputStream;

    public override Stream ChainStream(Stream stream)
    {
    Stream result = stream;
    if ((output))
    {
    httpOutputStream = stream;
    chainedOutputStream = new MemoryStream();
    result = chainedOutputStream;
    }
    else
    {
    output = true;
    }
    return result;
    }

    public override object GetInitializer(System.Type serviceType)
    {
    return null;
    }

    public override object
    GetInitializer(System.Web.Services.Protocols.LogicalMethodInfo
    methodInfo, System.Web.Services.Protocols.SoapExtensionAttribute
    attribute)
    {
    return null;
    }

    public override void Initialize(object initializer)
    {
    }

    public override void ProcessMessage(SoapMessage message)
    {
    if (message.Stage == SoapMessageStage.AfterDeserialize)
    {
    HttpContext.Current.Request.InputStream.Position = 0;
    HttpContext.Current.Items["SoapInputStream"] =
    HttpContext.Current.Request.InputStream;
    appOutputStream = new MemoryStream();
    HttpContext.Current.Items["SoapOutputStream"] =
    appOutputStream;
    }
    else if (message.Stage == SoapMessageStage.AfterSerialize)
    {
    chainedOutputStream.Position = 0;
    XmlReader reader = new
    XmlTextReader(chainedOutputStream);
    reader.ReadStartElement("Envelope",
    "http://schemas.xmlsoap.org/soap/envelope/");
    reader.MoveToContent();
    if ((reader.LocalName == "Header"))
    {
    reader.Skip();
    }
    reader.ReadStartElement("Body",
    "http://schemas.xmlsoap.org/soap/envelope/");
    reader.MoveToContent();
    if ((reader.LocalName == "Fault" & reader.NamespaceURI
    == "http://schemas.xmlsoap.org/soap/envelope/"))
    {
    chainedOutputStream.Position = 0;
    CopyStream(chainedOutputStream, httpOutputStream);
    }
    else
    {
    appOutputStream.Flush();
    appOutputStream.Position = 0;
    CopyStream(appOutputStream, httpOutputStream);

    }
    appOutputStream.Close();
    }
    }

    private void CopyStream(Stream src, Stream dest)
    {
    StreamReader reader = new StreamReader(src);
    StreamWriter writer = new StreamWriter(dest);
    writer.Write(reader.ReadToEnd());
    writer.Flush();
    }

    public class SoapStreams
    {

    public static Stream InputMessage
    {
    get
    {
    return
    ((Stream)(HttpContext.Current.Items["SoapInputStream"]));
    }
    }

    public static Stream OutputMessage
    {
    get
    {
    return
    ((Stream)(HttpContext.Current.Items["SoapOutputStream"]));
    }
    }
    }
    [AttributeUsage(AttributeTargets.Method)]
    public class XmlStreamSoapExtensionAttribute :
    SoapExtensionAttribute
    {
    private int m_priority;
    public override Type ExtensionType
    {
    get{ return typeof(XmlStreamSoapExtension);}
    }

    public override int Priority
    {
    get {return m_priority;}
    set{m_priority = 1;}
    }
    }

    --*********************
    end of soap extension class
    --**********************

    --*********************
    --here is the asmx file --all it does is a simple transform of the
    input message
    --*********************

    using System;
    using System.Web;
    using System.Collections;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml;
    using System.Xml.Xsl;
    using System.Xml.Serialization;
    [System.Web.Services.WebServiceBindingAttribute(Name = "Arithmetic",
    Namespace = "urn:msdn-microsoft-com:hows")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class arithmetic : WebService {

    private const string soapURI =
    "http://schemas.xmlsoap.org/soap/envelope/";
    private const string nsURI = "urn:msdn-microsoft-com:hows";

    [XmlStreamSoapExtension]
    [WebMethod]
    [SoapDocumentMethod("urn:msdn-microsoft-com:hows/Add", Use =
    System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle
    = System.Web.Services.Protocols.SoapParameterStyle.Bare)]
    [return: XmlElement("AddResponse", Namespace =
    "urn:msdn-microsoft-com:hows")]
    public /* AddResponse */ void Add(/* Add Add1 */)
    {
    //************
    //this will transform the input stream (in a reader) directly
    to output stream
    //************
    XslCompiledTransform docXsl = new XslCompiledTransform();
    XsltSettings xslset = new XsltSettings();
    xslset.EnableDocumentFunction = true;
    string xslsource = "add.xslt";
    XmlUrlResolver resolver = new XmlUrlResolver();
    string pathxsl = HttpContext.Current.Server.MapPath(xslsource);
    docXsl.Load(new XmlTextReader(pathxsl), xslset, resolver);
    docXsl.Transform(xReader, new
    XmlTextWriter(SoapStreams.OutputMessage, System.Text.Encoding.UTF8));
    }
    public arithmetic () {
    //Uncomment the following line if using designed components
    //InitializeComponent();
    }

    }

    --***************************
    --end of the asmx file
    --****************************


    --**********************
    --here is the xml message sent to the service by the client w/soap
    action of
    --"urn:msdn-microsoft-com:hows/Add"
    --which works fine as it fires the service up
    --************************

    <?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><Add
    xmlns='urn:msdn-microsoft-com:hows'><n1>10</n1><n2>20</n2></Add></soap:Body></soap:Envelope>

    --*****************
    --end of the input message
    --*****************

    --*****************
    --here is the add.xslt file
    --****************
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xsl:version="1.0">
    <soap:Body>
    <ns:AddResponse xmlns:ns="urn:msdn-microsoft-com:hows">
    <ns:sum>
    <xsl:value-of select="sum(//ns:Add/*/text())"/>
    </ns:sum>
    </ns:AddResponse>
    </soap:Body>
    </soap:Envelope>

    --******************
    --end of add.xslt file
    --******************
    , Nov 1, 2006
    #1
    1. Advertising

  2. Guest

    sorry forgot to include the xreader creation in the asmx code file.
    Here it is, insert this into the asmx code before you use the xreader

    XmlReaderSettings settings = new XmlReaderSettings();
    SoapStreams.InputMessage.Position = 0;
    XmlReader xReader = XmlReader.Create(new
    XmlTextReader(SoapStreams.InputMessage),settings);
    while (xReader.Read())
    {
    }
    , Nov 1, 2006
    #2
    1. Advertising

  3. Guest

    could this be due to the new plumbing in vs 2005 webservices? It wants
    all the code in the app_code directory and maybe when you put classes
    in there they don't know what is really going on, i.e., in the process
    they are losing their connection to the webservices http pipeline?
    maybe there is a parallel pipeline created that is running too and that
    is why I hit afterserialize twice?

    btw, in case you didn't figure it out, all the .cs code for this app is
    in the app_code directory except for the asmx file (even the asmx.cs is
    in app_code) per the recommendation of VS when you create these
    classes.

    If app_code classes are running in a parallel (disconnected) process
    then why do my soap exceptions work? For example, if I purposely put a
    exception in the asmx.cs file, e.g,, int x = 1/0;, then the
    afterserialize event sees the exception and correctly sends the regular
    output stream (do you call this the chained stream?) and not my
    appoutputstream.
    , Nov 1, 2006
    #3
  4. Guest

    BTW, the only changes I made to the web.config are below. I really
    don't like using 'App_Code' as the class for my soap extension type,
    but that is what it took to make it work and apparently that is what VS
    2005 wants you to do, i.e., put everything in that directory.

    <webServices>
    <soapExtensionTypes>
    <add type="XmlStreamSoapExtension, App_Code" priority="1"
    group="High"/>
    </soapExtensionTypes>
    <protocols>
    <remove name="HttpGet" />
    <remove name="HttpPost" />
    <remove name="Documentation" />
    </protocols>
    </webServices>
    , Nov 1, 2006
    #4
  5. Guest

  6. Guest

    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Damon Payne
    Replies:
    0
    Views:
    9,118
    Damon Payne
    Mar 8, 2005
  2. Robert Rotstein
    Replies:
    0
    Views:
    2,792
    Robert Rotstein
    Dec 21, 2005
  3. Jesús Bosch
    Replies:
    1
    Views:
    13,049
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
    Jul 3, 2006
  4. Vish Ramachandran

    Client found response content type of '', but expected 'text/xml'

    Vish Ramachandran, May 9, 2004, in forum: ASP .Net Web Services
    Replies:
    1
    Views:
    197
    Martin Boehm
    May 26, 2004
  5. Søren M. Olesen
    Replies:
    4
    Views:
    524
    Dan Rogers
    Feb 15, 2005
Loading...

Share This Page