C# Mapping XML Response into Unknown Class -


i'm trying achieve generic solution sending , receiving xml via means(ip, serial textfiles, etc)

all appears work fine until response string.

what need cast response sting correct class type (loginresponse, logoffresponse, cardpaymentresponse) etc.

i cant generic way cast xml object in efficient manner.

heres have got far:

sample response strings:

xml loginresponse:

<?xml version="1.0" encoding="utf-8" standalone="no"?> <serviceresponse requesttype="login" applicationsender="possel01"     workstationid="1" requestid="1254" protocolversion="000000001234" devicetype="113" swchecksum="ac3f" communicationprotocol="000000000432" model="011" applicatiosoftwareversion="000000000100" manufacturer_id="023" overallresult="success" xmlns="http://www.nrf-arts.org/ixretail/namespace" xmlns:ifsf="http://www.ifsf.org/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.nrf-arts.org/ixretail/namespace c:\schema\serviceresponse.xsd"/> 

xml logoffresponse:

<?xml version="1.0" encoding="utf-8" standalone="no"?> <serviceresponse requesttype="logoff" applicationsender="possel01" workstationid="1" requestid="1254" overallresult="success" xmlns="http://www.nrf-arts.org/ixretail/namespace" xmlns:ifsf="http://www.ifsf.org/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.nrf-arts.org/ixretail/namespace c:\schema\serviceresponse.xsd"/> 

xml cardpaymentresponse:

<cardserviceresponse  xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema"  requesttype="cardpayment"  applicationsender="1"  workstationid="1"  requestid="1254"  overallresult="loggedout"> <terminal      terminalid="1234"      terminalbatch="1"      stan="55" /> <tender>     <totalamount          currency="eur">0.00</totalamount> </tender> </cardserviceresponse> 

code base class contain common fields

public abstract class ifsfresponsebase {     [xmlattribute()]     public string requesttype { get; set; }      [xmlattribute()]     public string applicationsender { get; set; }      [xmlattribute()]     public string workstationid { get; set; }      [xmlattribute()]     public string requestid { get; set; }      [xmlattribute()]     public string overallresult { get; set; } } 

serviceresponse type, no additional fields here

public class serviceresponse : ifsfresponsebase {  } 

cardserviceresponse type, common fields here

public class cardserviceresponse : ifsfresponsebase {     [xmlelement("terminal")]     public cardserviceresponseterminal terminal     { get; set; }      [xmlelement("tender")]     public cardserviceresponsetender tender     {         get; set;     } } 

cardserviceresponse helper classes

public class cardserviceresponseterminal {     [xmlattribute()]     public string terminalid { get; set; }      [xmlattribute()]     public string terminalbatchfield { get; set; }      [xmlattribute()]     public string stanfield { get; set; }  }  public class cardserviceresponsetender {     [xmlelement("totalamount")]     public cardserviceresponsetendertotalamount totalamount { get; set; } }  public class cardserviceresponsetendertotalamount {     private string valuefield;      [xmlattribute()]     public string cashbackamount     {         get;         set;     }      [xmlattribute()]     public string currency     {         get;         set;     }      [xmltext()]     public string value     {                 {             return this.valuefield;         }         set         {             this.valuefield = value;         }     } } 

concrete logoffresponse class, no additional fields

[xmlroot("serviceresponse")] public class logoffresponse : serviceresponse {  } 

concrete loginresponse class, fields handled

[xmlroot("serviceresponse")] public class loginresponse : serviceresponse {     [xmlattribute()]     public string popid { get; set; }      [xmlattribute()]     public string referencenumber { get; set; }      [xmlattribute()]     public string protocolversion { get; set; }      [xmlattribute()]     public string devicetype { get; set; }      [xmlattribute()]     public string swchecksum { get; set; }      [xmlattribute()]     public string communicationprotocol { get; set; }      [xmlattribute()]     public string model { get; set; }      [xmlattribute()]     public string applicatiosoftwareversion { get; set; }      [xmlattribute()]     public string manufacturer_id { get; set; }  } 

concrete cardpaymentresponse class, no additional fields

[xmlroot("cardserviceresponse")] public class cardpaymentresponse : cardserviceresponse {  } 

concrete cardpaymentrefundresponse class, data needed

[xmlroot("cardserviceresponse")] public class cardpaymentrefundresponse : cardserviceresponse {     [xmlattribute()]     public string extravalue { get; set; } } 

helper class remove name space response

public class namespaceignorantxmltextreader : xmltextreader {     public namespaceignorantxmltextreader(system.io.textreader reader) : base(reader) { }      public override string namespaceuri     {         { return ""; }     } } 

with code below, don't know actual response receive until parsed, don't know can use in place of concrete class (in case serviceresponse).

try {     xmlserializer serializer = new xmlserializer(typeof(serviceresponse));      stringreader sr = new stringreader(xmlresponse);      namespaceignorantxmltextreader xmlwithoutnamespace = new namespaceignorantxmltextreader(sr);      return (serviceresponse)serializer.deserialize(xmlwithoutnamespace);  } catch (exception ex) {     //breakpoint code here debugging atm, removed     throw; } 

that fine logoff response type, not if loginresponse type.

so use loginresponse if response cardserviceresponse fail exception since root element not serviceresponse cardserviceresponse

try {     xmlserializer serializer = new xmlserializer(typeof(loginresponse));      stringreader sr = new stringreader(xmlresponse);      namespaceignorantxmltextreader xmlwithoutnamespace = new namespaceignorantxmltextreader(sr);      return (loginresponse)serializer.deserialize(xmlwithoutnamespace);  } catch (exception ex) {     //breakpoint code here debugging atm, removed     throw; } 

i tried following hack , work i'm wondering if there better way achieve this

private object internalparse(string sxml)     {         object oretval = null;          try         {             xmldocument xmldoc = new xmldocument();             xmldoc.loadxml(sxml);             xmlnode reqtype = xmldoc.documentelement.attributes.getnameditem("requesttype");              assembly asm = assembly.getexecutingassembly();              type type = asm.gettype(asm.getname().name + "." + reqtype.value + "response");              object instance = null;              try             {                 instance = (object)activator.createinstance(type);             }             catch             {                 //problem creating type requesttype name + response appended on, class                 //probably not exist. lets create parent class                 type = asm.gettype(asm.getname().name + "." + xmldoc.documentelement.name);                 instance = (object)activator.createinstance(type);             }              xmlserializer serializer = new xmlserializer(instance.gettype());              stringreader sr = new stringreader(sxml);              namespaceignorantxmltextreader xmlwithoutnamespace = new namespaceignorantxmltextreader(sr);              oretval = serializer.deserialize(xmlwithoutnamespace);         }         catch (exception ex)         {             //log ex here         }          return oretval;     } 

thanks in advance


Comments

Popular posts from this blog

Android : Making Listview full screen -

javascript - Parse JSON from the body of the POST -

javascript - How to Hide Date Menu from Datepicker in yii2 -