Convert CookComputing XMLRpcStruct (IEnumerable <Object>) to a valid C # class

So, I use the CookComputings XMLRPC library to be able to talk with InfusionSoft (this is an online CRM that is pretty popular). The main method:

  [XmlRpcMethod("DataService.query")] IEnumerable<object> QuerySubscriptionStatus(string apiKey, string table, int limit, int page, IDictionary queryData, string[] selectedFields); 

I MUST use an IEnumerable<object> , unfortunately, this requires the InfusionSoft XML / RPC API. I am sorry that this is not so, but unfortunately it is.

Since I am using .NET 4.5, I decided that I could just do the dyanmic cast:

  var subStatus = proxy.QuerySubscriptionStatus( _key, "RecurringOrder", 500, 0, dict, sarray); var result = subStatus.Cast<SubscriptionStatus>(); 

Unfortunately this will not work, I got a very frustrated error from C #:

Cannot pass an object of type "CookComputing.XmlRpc.XmlRpcStruct" to enter "WBI.Model.SubscriptionStatus".

I tried to specify my class as struct ; hell, I even tried to specify it with XMLRpcMember() tags, but no, it just doesn't convert.

How can I interact with data in IEnumerable ?

Class / structure types I've tried

 public struct SubStatus { public int AffiliateId; public int AutoCharge; public double BillingAmt; public string BillingCycle; public int CC1; public int CC2; public int ContactId; public DateTime EndDate; public int Frequency; public int Id; public DateTime LastBillDate; public int LeadAffiliateId; public int MaxRetry; public int MerchantAccountId; public DateTime NextBillDate; public int NumDaysBetweenRetry; public int OriginatingOrderId; public DateTime PaidThruDate; public int PaymentGatewayId; public int ProductId; public int ProgramId; public string PromoCode; public int Qty; public string ReasonStopped; public int ShippingOptionId; public DateTime StartDate; public string Status; public int SubscriptionPlanId; } 

I also just tried a simple class with XMLRpcMember tags:

 public class SubscriptionStatus { [XmlRpcMember("AffiliateId")] public int AffiliateId { get; set; } [XmlRpcMember("AutoCharge")] public int AutoCharge { get; set; } [XmlRpcMember("BillingAmt")] public double BillingAmt { get; set; } [XmlRpcMember("BillingCycle")] public string BillingCycle { get; set; } [XmlRpcMember("CC1")] public int CC1 { get; set; } [XmlRpcMember("CC2")] public int CC2 { get; set; } [XmlRpcMember("ContactId")] public int ContactId { get; set; } [XmlRpcMember("EndDate")] public DateTime EndDate { get; set; } [XmlRpcMember("Frequency")] public int Frequency { get; set; } [XmlRpcMember("Id")] public int Id { get; set; } [XmlRpcMember("LastBillDate")] public DateTime LastBillDate { get; set; } [XmlRpcMember("LeadAffiliateId")] public int LeadAffiliateId { get; set; } [XmlRpcMember("MaxRetry")] public int MaxRetry { get; set; } [XmlRpcMember("MerchantAccountId")] public int MerchantAccountId { get; set; } [XmlRpcMember("NextBillDate")] public DateTime NextBillDate { get; set; } [XmlRpcMember("NumDaysBetweenRetry")] public int NumDaysBetweenRetry { get; set; } [XmlRpcMember("OriginatingOrderId")] public int OriginatingOrderId { get; set; } [XmlRpcMember("PaidThruDate")] public DateTime PaidThruDate { get; set; } [XmlRpcMember("PaymentGatewayId")] public int PaymentGatewayId { get; set; } [XmlRpcMember("ProductId")] public int ProductId { get; set; } [XmlRpcMember("ProgramId")] public int ProgramId { get; set; } [XmlRpcMember("PromoCode")] public string PromoCode { get; set; } [XmlRpcMember("Qty")] public int Qty { get; set; } [XmlRpcMember("ReasonStopped")] public string ReasonStopped { get; set; } [XmlRpcMember("ShippingOptionId")] public int ShippingOptionId { get; set; } [XmlRpcMember("StartDate")] public DateTime StartDate { get; set; } [XmlRpcMember("Status")] public string Status { get; set; } [XmlRpcMember("SubscriptionPlanId")] public int SubscriptionPlanId { get; set; } } 
+5
source share
2 answers

So, after some extended help from another senior developer, it turned out that we were able to make some changes to the structure:

  private string[] retFlds = { "Id", "ContactId", "OriginatingOrderId", "ProgramId", "SubscriptionPlanId", "ProductId", "StartDate", "NextBillDate", "BillingCycle", "Frequency", "BillingAmt", "Status", "ReasonStopped", "AutoCharge", "CC1", "CC2", "NumDaysBetweenRetry", "MaxRetry", "MerchantAccountId", "AffiliateId", "PromoCode", "LeadAffiliateId", "Qty", "ShippingOptionId" }; private string table = "RecurringOrder"; private DataTable dt = new DataTable(); // here the query XmlRpcStruct[] retData = proxy.Query(Auth.key, table, 1000, 0, qryData, returnFields); dt = StructArrayToDT(retData); public static DataTable StructArrayToDT(XmlRpcStruct[] data) { DataTable dt = new DataTable(); if (data.Length == 0) { return dt; } // do columns foreach (DictionaryEntry d in data[0]) { dt.Columns.Add(d.Key.ToString(), typeof(object)); } foreach (XmlRpcStruct xmlstruct in data) { DataRow dr = dt.NewRow(); foreach (DictionaryEntry d in xmlstruct) { try { dr[d.Key.ToString()] = d.Value; } catch (Exception ex) { // handle errors } } dt.Rows.Add(dr); } return dt; } 

Finally, you can access this data without any problems.

+1
source

Looking at the signature of QuerySubscriptionStatus, it returns IEnumerable. Again, if you look at the definition of XmlRpcStruct ( Fork of XML.Rpc.Net ), which implements IDictionary, ICollection, IEnumerable. Therefore, assuming that QuerySubscriptionStatus returns an XmlRpcStruct that implements IEnumerable, then you get Enumeration in the answer, which is essentially a collection of elements (even if it contains one element). You are trying to convert an enumeration type to a structure (SubscriptionStatus), which is not a collection. Hence the error. If the elements contained in Enumeration have a SubscriptionStatus structure of type, the next line should do the trick.

 var resultList = subStatus.ToList<SubscriptionStatus(); 

and then run the resultList loop to access the response from the QuerySubscriptionStatus method.

 foreach(var result in resultList) { } 

OR, if you are sure that there will be one entry in the answer list, you can also use the following

 var result = resultList.FirstOrDefault(); 

Hope this helps.

0
source

Source: https://habr.com/ru/post/1264764/


All Articles