Interoperability for Document-Based Web Services (ASP.NET)
How to manipulate xsd:anyType in asp.net web service, JWSDP, and gSOAP
This is the first part about ASP.NET
Two good papers are at
http://java.sun.com/developer/technicalArticles/xml/jaxrpcpatterns/index.html
http://java.sun.com/developer/technicalArticles/xml/jaxrpcpatterns2/
Overall, there are five approaches to use document-based web services.
* Using XML in the SOAP Body
* Using a String in the SOAP Body
* Using base64Encoded or raw bytes in the SOAP body
* Using the xsd:any Element in WSDL
* Using the xsd:anyType in WSDL
We will use xsd:anyType for interoperability. And the purpose is to have a state management web service.
It is like a web service based hash table. By the key (xsd:string), client can put/get the value (xsd:anyType) afterwards.
The web service will maintain the stateful information for client. The xml serialization class could be created on the fly.
The assumption is contract first approach, that is, we have a WSDL definition beforehand.
<!-- put state -->
<xsd:element name="putStateRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="key" />
<xsd:element type="xsd:anyType" name="value" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="putStateResponse">
<xsd:complexType />
</xsd:element>
<!-- get state -->
<xsd:element name="getStateRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="key" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
ASP.net web service
It will use System.Object to map xsd:anyType.
- use xmlserializer to do the serialization and deserialization. The only overhead is to declare a normal class.
- create a class to implement IXmlSerializable to take over the control of read/write xml. Resource 5 gave a thorough example to control everything by overriding xmlwriter.
The arbitrary class is defined as
public class myObject
{
public int i;
public float f;
public string s;
};
The code example for approach 1 is:
The helper function is from Resources 3.
public static string XmlString(object o)
{
StringWriter writer = null;
try
{
XmlSerializer formatter = new XmlSerializer(o.GetType());
writer = new StringWriter();
formatter.Serialize(writer, o);
return writer.ToString();
}
finally
{
if (writer != null) writer.Close();
}
}
public static object XmlString(string xml, Type type)
{
StringReader reader = null;
try
{
XmlSerializer formatter = new XmlSerializer(type);
reader = new StringReader(xml);
return formatter.Deserialize(reader);
}
finally
{
if (reader != null) reader.Close();
}
}
Testing code
myObject m=new myObject();
m.i = 4;
m.f = 1.3F;
m.s = "hello";
string xmlStr = XmlString(m);
putReq.value = (object)xmlStr;
service.putState(putReq);
getResp = service.getState(getReq);
myObject ret = (myObject)XmlString((string)getResp.getStateResult, m.GetType());
Console.WriteLine(ret.i);
Console.WriteLine(ret.f);
Console.WriteLine(ret.s);
The code example for approach 2 is:
public class myObject2 : IXmlSerializable
{
public int i;
public float f;
public string s;
public XmlSchema GetSchema()
{
return null;
}
public void WriteXml(XmlWriter w)
{
w.WriteStartElement("i");
w.WriteString(i.ToString());
w.WriteEndElement();
w.WriteStartElement("f");
w.WriteString(f.ToString());
w.WriteEndElement();
w.WriteStartElement("s");
w.WriteString(s);
w.WriteEndElement();
}
public void ReadXml(XmlReader r)
{
string str;
r.Read();
r.ReadStartElement("i");
str = r.ReadString();
i = Convert.ToInt32(str);
r.ReadEndElement();
r.ReadStartElement("f");
str = r.ReadString();
f = Convert.ToSingle(str);
r.ReadEndElement();
r.ReadStartElement("s");
s = r.ReadString();
r.ReadEndElement();
}
}
Testing code
myObject2 m2 = new myObject2();
m2.i = 5;
m2.f = 3.4F;
m2.s = "world";
putReq.value = (string)XmlString(m2);
service.putState(putReq);
getResp = service.getState(getReq);
myObject2 ret2 = (myObject2)XmlString((string)getResp.getStateResult, m2.GetType());
Console.WriteLine(ret2.i);
Console.WriteLine(ret2.f);
Console.WriteLine(ret2.s);
Resources
1. Trouble shooting for xmlserializer
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnxmlnet/html/trblshtxsd.asp
2. Tutorial of xmlserializer
http://www.topxml.com/xmlserializer/default.asp
3. serialization/de-serialization helper functions in C#
http://lewismoten.blogspot.com/2005/02/demonstrating-serialization-in-net.html
4. Customize XML Serialization using IXmlSerializable
http://wwww.developerfusion.com/show/4639/
5. .NET XML and SOAP serialization samples
http://www.codeproject.com/soap/Serialization_Samples.asp
http://aspzone.com/blogs/john/articles/167.aspx