Jay Jay - 3 months ago 27
C# Question

Deserialization of XML into C# class not working as expected

I am working with the Realex XML API to send 3D secure enrolment requests to the MPI server using a GitHub .Net Library found here:
https://github.com/JonCanning/RealEx.NET

The first two steps of the authentication process are working well for the 3D secure test card 4012001037141112 which should result in a successful 3D secure authetntication but upon trying to deserialize the XML below the .Net class ThreeDSecure is never being populated and is always null despite the XML being populated accordingly:

<response timestamp="20160830142152">
<merchantid>*****</merchantid>
<account>internet</account>
<orderid>92f669c7-6fb3-43e0-bfb9-8f62aca128cf</orderid>
<authcode />
<result>00</result>
<message>Authentication Successful</message>
<pasref />
<timetaken>0</timetaken>
<authtimetaken>0</authtimetaken>
<threedsecure>
<status>Y</status>
<eci>5</eci>
<cavv>AAACBDlZYkmAggkgJVliAAAAAAA=</cavv>
<xid>ZFD6gQMih8V5gzA3q/XODcrx8N8=</xid>
<algorithm>2</algorithm>
</threedsecure>
<sha1hash>a9800768d3e683de4cf074195884d67d29f79189</sha1hash>
</response>


The code for the .Net classes are as follows:

namespace RealEx
{
[XmlRoot("response")]
public class RealExResponse
{
[XmlElement("result")]
public string Result { get; set; }
[XmlElement("message")]
public string Message { get; set; }
[XmlElement("pasref")]
public string PasRef { get; set; }
[XmlElement("authcode")]
public string AuthCode { get; set; }
[XmlElement("pareq")]
public string PaReq { get; set; }
[XmlElement("enrolled")]
public string Enrolled { get; set; }
[XmlElement("xid")]
public string Xid { get; set; }
[XmlElement("orderid")]
public string OrderId { get; set; }
[XmlElement("sha1hash")]
public string Sha1Hash { get; set; }
[XmlElement("merchantid")]
public string MerchantId { get; set; }
[XmlElement("account")]
public string Account { get; set; }
[XmlElement("timetaken")]
public string TimeTaken { get; set; }
[XmlElement("authtimetaken")]
public string AuthTimeTaken { get; set; }
[XmlElement("url")]
public string Url { get; set; }
[XmlAttribute("timestamp")]
public string TimeStamp { get; set; }
[XmlElement("threedsecure")]
public ThreeDSecure ThreeDSecure { get; set; }
[XmlElement("cvnresult")]
public string CvnResult { get; set; }
[XmlElement("avspostcoderesponse")]
public string AvsPostcodeResponse { get; set; }
[XmlElement("avsaddressresponse")]
public string AvsAddressResponse { get; set; }
[XmlElement("batchid")]
public string BatchId { get; set; }
[XmlElement("cardissuer")]
public CardIssuer CardIssuer { get; set; }

internal static RealExResponse Deserialize(string xml)
{
return new XmlSerializer(typeof(RealExResponse)).Deserialize(XDocument.Parse(xml).CreateReader()) as RealExResponse;
}
}
}


namespace RealEx
{
public class ThreeDSecure
{
public string Status { get; set; }
public string Eci { get; set; }
public string Cavv { get; set; }
public string Xid { get; set; }
public string Algorithm { get; set; }
}
}

namespace RealEx
{
public class RealEx3DAuthRequest : RealExAuthRequest
{
public RealEx3DAuthRequest(string secret, string merchantId, string account, string orderId, Amount amount, Card card, TssInfo tssInfo, ThreeDSecure threeDSecure, bool autoSettle, string custNum, string prodId, string varRef, Comments comments)
: base(secret, merchantId, account, orderId, amount, card, tssInfo, autoSettle, custNum, prodId, varRef, comments)
{
Mpi = new Mpi(threeDSecure.Cavv, threeDSecure.Xid, threeDSecure.Eci);
}
public Mpi Mpi { get; private set; }
}
}


I cant understand why the information received in the response is not being written to the class when all of the other properties are being written correctly can anyone help me understand this problem?

Answer

Your ThreeDSecure properties don't match the names in your XML. Either change the names to match (i.e. change the casing) or add the appropriate attributes:

public class ThreeDSecure
{
    [XmlElement("status")]
    public string Status { get; set; }
    [XmlElement("eci")]
    public string Eci { get; set; }
    [XmlElement("cavv")]
    public string Cavv { get; set; }
    [XmlElement("xid")]
    public string Xid { get; set; }
    [XmlElement("algorithm")]
    public string Algorithm { get; set; }
}

As an aside, there's no need to parse your XML into the DOM before deserializing. Just use a StringReader instead:

using (var reader = new StringReader(xml))
{
    return (RealExResponse)new XmlSerializer(typeof(RealExResponse)).Deserialize(reader);
}