SYMPTOMS
Microsoft Web Services Enhancements (WSE) 3.0 for Microsoft .NET serializes a custom data type incorrectly when the following conditions are true:
- The data type has a property that is marked as an XmlAttribute class.
- This property has the byte array (byte[]) data type.
When these conditions are true, WSE 3.0 does not serialize the attribute value to an
elements attribute. The attribute value is added to the next
class property if one exists. This problem occurs in a WSE 3.0-enabled client application or in a WSE 3.0-enabled Web service.
WORKAROUND
To work around this problem, use one of the following methods.
Method 1
Change the data type of the user data from the byte array data type to the string data type. Then, write additional code for the client application or for the Web service to convert the byte array to a string and then back to a byte array as needed. To do this, use the
Convert.ToBase64String method and the
Convert.FromBase64String method.
Method 2
Create a new class in the client application that is derived from the Web service proxy class (the
WebService class). In the new class, override the
GetWriterForMessage method. The
GetWriterForMessage method returns an
XmlWriter class implementation. The
XmlWriter class implementation delegates all operations except for the
WriteBase64 method to the
XmlWriter class instance that is returned by the base class. The
WriteBase64 method implementation must be delegated to the wrapped writer if the
WriteState enumeration is not the
Attribute member. Otherwise, the
WriteBase64 method should convert the byte array to a string.
The following code sample is an example of the new class and of the overridden methods. For this code sample to compile correctly, you must implement the rest of the
XmlWriter class methods.
class WorkaroundMyWebService : localhost.MyWebServiceWse
{
public WorkaroundMyWebService(): base() { }
protected override System.Xml.XmlWriter GetWriterForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize)
{
return new XmlWrappingWriter(base.GetWriterForMessage(message, bufferSize));
}
class XmlWrappingWriter : XmlWriter
{
XmlWriter writer;
public XmlWrappingWriter(XmlWriter baseWriter)
{
if (baseWriter == null)
throw new ArgumentNullException("writer");
this.writer = baseWriter;
}
public override XmlWriterSettings Settings { get { return writer.Settings; } }
public override WriteState WriteState { get { return writer.WriteState; } }
public override XmlSpace XmlSpace { get { return writer.XmlSpace; } }
public override string XmlLang { get { return writer.XmlLang; } }
-
public override void WriteStartDocument()
{
writer.WriteStartDocument();
}
public override void WriteBase64(byte[] buffer, int index, int count)
{
if (this.WriteState == WriteState.Attribute)
{
writer.WriteString(Convert.ToBase64String(buffer, index, count));
}
else
{
writer.WriteBase64(buffer, index, count);
}
}
//Implement the rest of the XmlWriter methods
//...
}
}
Additionally, change the client application to use the following derived proxy class.
localhost.MyWebServiceWse WseWebSvc = new WorkaroundMyWebService();
string WseResultString = WseWebSvc.AnalyzeMyObject(myobj);
Console.WriteLine(WseResultString.ToString());