Remove redundant xml namespaces from soapenv:Body
- by drachenstern
If you can tell me the magic google term that instantly gives me clarification, that would be helpful.
Here's the part that's throwing an issue when I try to manually deserialize from a string:
xsi:type="ns1:errorObject" xmlns:ns1="http://www.example.org/Version_3.0"
xsi:type="ns2:errorObject" xmlns:ns2="http://www.example.org/Version_3.0"
xsi:type="ns3:errorObject" xmlns:ns3="http://www.example.org/Version_3.0"
Here's how I'm deserializing by hand to test it: (in an aspx.cs page with a label on the front to display the value in that I can verify by reading source) (second block of XML duplicates the first but without the extra namespaces)
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {
string sourceXml = @"<?xml version=""1.0""?>
<InitiateActivityResponse xmlns=""http://www.example.org/Version_3.0"">
<InitiateActivityResult>
<errorObject errorString=""string 1"" eventTime=""2010-05-21T21:19:15.775Z"" nounType=""Object"" objectID=""object1"" xsi:type=""ns1:errorObject"" xmlns:ns1=""http://www.example.org/Version_3.0"" />
<errorObject errorString=""string 2"" eventTime=""2010-05-21T21:19:15.791Z"" nounType=""Object"" objectID=""object2"" xsi:type=""ns2:errorObject"" xmlns:ns2=""http://www.example.org/Version_3.0"" />
<errorObject errorString=""string 3"" eventTime=""2010-05-21T21:19:15.806Z"" nounType=""Object"" objectID=""object3"" xsi:type=""ns3:errorObject"" xmlns:ns3=""http://www.example.org/Version_3.0"" />
</InitiateActivityResult>
</InitiateActivityResponse>
";
sourceXml = @"<?xml version=""1.0""?>
<InitiateActivityResponse xmlns=""http://www.example.org/Version_3.0"">
<InitiateActivityResult>
<errorObject errorString=""string 1"" eventTime=""2010-05-21T21:19:15.775Z"" nounType=""Object"" objectID=""object1"" />
<errorObject errorString=""string 2"" eventTime=""2010-05-21T21:19:15.791Z"" nounType=""Object"" objectID=""object2"" />
<errorObject errorString=""string 3"" eventTime=""2010-05-21T21:19:15.806Z"" nounType=""Object"" objectID=""object3"" />
</InitiateActivityResult>
</InitiateActivityResponse>
";
InitiateActivityResponse fragment = new InitiateActivityResponse();
Type t = typeof( InitiateActivityResponse );
StringBuilder sb = new StringBuilder();
TextWriter textWriter = new StringWriter( sb );
TextReader textReader = new StringReader( sourceXml );
XmlTextReader xmlTextReader = new XmlTextReader( textReader );
XmlSerializer xmlSerializer = new XmlSerializer( t );
object obj = xmlSerializer.Deserialize( xmlTextReader );
fragment = (InitiateActivityResponse)obj;
xmlSerializer.Serialize( textWriter, fragment );
//I have a field on my public page that I write to from sb.ToString();
}
}
Consuming a webservice, I have a class like thus: (all examples foreshortened to as little as possible to show the problem, if boilerplate is missing, my apologies) (this is where I think I want to remove the troublespot)
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute( "code" )]
[System.Web.Services.WebServiceBindingAttribute( Name = "MyServerSoapSoapBinding", Namespace = "http://www.example.org/Version_3.0" )]
public partial class MyServer : System.Web.Services.Protocols.SoapHttpClientProtocol {
public MsgHeader msgHeader { get; set; }
public MyServer () {
this.Url = "localAddressOmittedOnPurpose";
}
[System.Web.Services.Protocols.SoapHeaderAttribute( "msgHeader" )]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute( "http://www.example.org/Version_3.0/InitiateActivity", RequestNamespace = "http://www.example.org/Version_3.0", ResponseNamespace = "http://www.example.org/Version_3.0", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped )]
[return: System.Xml.Serialization.XmlElementAttribute( "InitiateActivityResponse" )]
public InitiateActivityResponse InitiateActivity(string inputVar) {
object[] results = Invoke( "InitiateActivity", new object[] { inputVar } );
return ( (InitiateActivityResponse)( results[0] ) );
}
}
Class descriptions
[System.SerializableAttribute]
[System.Diagnostics.DebuggerStepThroughAttribute]
[System.ComponentModel.DesignerCategoryAttribute( "code" )]
[XmlType( Namespace = "http://www.example.org/Version_3.0", TypeName = "InitiateActivityResponse" )]
[XmlRoot( Namespace = "http://www.example.org/Version_3.0" )]
public class InitiateActivityResponse {
[XmlArray( ElementName = "InitiateActivityResult", IsNullable = true )]
[XmlArrayItem( ElementName = "errorObject", IsNullable = false )]
public errorObject[] errorObject { get; set; }
}
[System.SerializableAttribute]
[System.Diagnostics.DebuggerStepThroughAttribute]
[System.ComponentModel.DesignerCategoryAttribute( "code" )]
[XmlTypeAttribute( Namespace = "http://www.example.org/Version_3.0" )]
public class errorObject {
private string _errorString;
private System.DateTime _eventTime;
private bool _eventTimeSpecified;
private string _nounType;
private string _objectID;
[XmlAttributeAttribute]
public string errorString {
get { return _errorString; }
set { _errorString = value; }
}
[XmlAttributeAttribute]
public System.DateTime eventTime {
get { return _eventTime; }
set { _eventTime = value; }
}
[XmlIgnoreAttribute]
public bool eventTimeSpecified {
get { return _eventTimeSpecified; }
set { _eventTimeSpecified = value; }
}
[XmlAttributeAttribute]
public string nounType {
get { return _nounType; }
set { _nounType = value; }
}
[XmlAttributeAttribute]
public string objectID {
get { return _objectID; }
set { _objectID = value; }
}
}
SOAP as it's being received (as seen by Fiddler2)
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<MsgHeader soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" AppName="AppName" AppVersion="1.0" Company="Company" Pwd="" UserID="" xmlns="http://www.example.org/Version_3.0"/>
</soapenv:Header>
<soapenv:Body>
<InitiateActivityResponse xmlns="http://www.example.org/Version_3.0">
<InitiateActivityResult>
<errorObject errorString="Explanatory string for request 1" eventTime="2010-05-24T21:21:37.477Z" nounType="Object" objectID="12345" xsi:type="ns1:errorObject" xmlns:ns1="http://www.example.org/Version_3.0"/>
<errorObject errorString="Explanatory string for request 2" eventTime="2010-05-24T21:21:37.493Z" nounType="Object" objectID="45678" xsi:type="ns2:errorObject" xmlns:ns2="http://www.example.org/Version_3.0"/>
<errorObject errorString="Explanatory string for request 3" eventTime="2010-05-24T21:21:37.508Z" nounType="Object" objectID="98765" xsi:type="ns3:errorObject" xmlns:ns3="http://www.example.org/Version_3.0"/>
</InitiateActivityResult>
</InitiateActivityResponse>
</soapenv:Body>
</soapenv:Envelope>
Okay, what should I have not omitted? No I won't post the WSDL, it's hosted behind a firewall, for a vertical stack product. No, I can't change the data sender. Is this somehow automagically handled elsewhere and I just don't know what I don't know?
I think I want to do some sort of message sink leading into this method, to intercept the soapenv:Body, but obviously this is for errors, so I'm not going to get errors every time. I'm not entirely sure how to handle this, but some pointers would be nice.