We return instances of the class AuthenticateUserOutput
from a WCF web service.
So we have this method:
public override AuthenticateUserOutput AuthenticateUser(AuthenticateUserInput AuthenticateUserInput)
AuthenicateUserOutput is auto generated:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.5420")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="xxxx")]
public partial class AuthenticateUserOutput : WS2MethodOutput
{
private bool authenticationResultField;
private UserContext userContextField;
/// <remarks/>
public bool AuthenticationResult
{
get
{
return this.authenticationResultField;
}
set
{
this.authenticationResultField = value;
}
}
/// <remarks/>
public UserContext UserContext
{
get
{
return this.userContextField;
}
set
{
this.userContextField = value;
}
}
}
We need to be able to de serialize as AuthenticateUserOutput
, but it's not working.
As a test, I instantiated an AuthenticateUserOutput
, serialized it and tried to de-serialize it.
It fails with InvalidOperationException.
Here's the serialized Xml:
<?xml version="1.0" encoding="utf-16"?>
<AuthenticateUserOutput xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="xxxx">
<Response xmlns="xxxx">
<IsValid>true</IsValid>
<Success>true</Success>
</Response>
<AuthenticationResult xmlns="xxxx">true</AuthenticationResult>
<UserContext xmlns="xxxx">
</UserContext>
</AuthenticateUserOutput>
Here's the serialization and de-serialization code:
public static string ToXml(this object input)
{
string output;
XmlSerializer serializer = new XmlSerializer(input.GetType());
StringBuilder sb = new StringBuilder();
using (TextWriter textWriter = new StringWriter(sb))
{
serializer.Serialize(textWriter, input);
}
output = sb.ToString();
return output;
}
And:
public static T FromXml<T>(this string input)
{
T output;
XmlSerializer serializer = new XmlSerializer(typeof(T));
output = (T)serializer.Deserialize(new StringReader(input));
return output;
}
The exact details of the exception:
System.InvalidOperationException occurred
Message="<AuthenticateUserOutput xmlns='xxxx'> was not expected."
Source="qkxd8dd-"
StackTrace:
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderAuthenticateUserOutput.Read31_AuthenticateUserOutput()
InnerException:
So it can't de-serialize it's own serialized Xml.
Can anybody see why?
Thanks,
J1M.
UPDATE: Here is the test code:
AuthenticateUserOutput test = new AuthenticateUserOutput();
test.AuthenticationResult = true;
test.Response = new ResponseType();
test.Response.Exception = null;
test.Response.IsValid = true;
test.Response.Success = true;
test.Response.ValidationErrors = null;
test.UserContext = new UserContext();
string serializedXml = test.ToXml();
AuthenticateUserOutput deserializedString = serializedXml.FromXml<AuthenticateUserOutput>();
UPDATE2: Deserializer works thanks to Mark Gravell
OK, I forgot I'd added this to get the namespaces to come out correctly when de-serializing:
public partial class WS2MethodInput
{
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces _xmlns;
/// <summary>
/// Constructor for WS2MethodInput that sets up default namespaces
/// </summary>
public WS2MethodInput()
{
_xmlns = new XmlSerializerNamespaces();
_xmlns.Add("", "xxxx");
}
}
With this, the serialized Xml is as it was at the top of this message. Without it, the de-serializer works but AuthenticateUserOutput is missing a namespace:
<?xml version="1.0" encoding="utf-16"?>
<AuthenticateUserOutput xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="xxxx">
<Response xmlns="xxxx">
<IsValid>true</IsValid>
<Success>true</Success>
</Response>
<AuthenticationResult xmlns="xxxx">true</AuthenticationResult>
<UserContext xmlns="xxxx">
</UserContext>
</AuthenticateUserOutput>
Note the xmlns="xxxx"
at the end of AuthenticateUserOutput
Problem is, now I can't use that Xml with our other code without either:
1) Loading it into an XDocument and adding the namespace and removing it when I need to de-serialize it 2) Doing the same with string replace of regex or something
Neither of which I really like. In fact that's horrible! 8X