Proxy/Wrapper class for a dynamic object from a SOAP API











up vote
6
down vote

favorite












I have to interface with a horrible PHP SOAP API that returns nested arrays of strings. I've written a helper that can parse the SOAP response and return a dynamic object but I need at least some properties to be strongly typed.



The API returns a lot more data that I need to keep up front (but need to interrogate later) and apart from a few guaranteed fields, it is truly dynamic (it could contain pretty much anything).



I have created a proxy class that wraps the dynamic object like so:



public class Basket
{
public Basket(string basketResponse, BasketToken token)
{
this.Token = token;
this.BasketResponse = new SoapSimplifier(basketResponse).ToJObject();
}

public string FirstName { get { return this.BasketResponse.deliverydata.firstname; } }
public string LastName { get { return this.BasketResponse.deliverydata.lastname; } }
public string Tel { get { return this.BasketResponse.deliverydata.mobile; } }
public string Email { get { return this.BasketResponse.deliverydata.email; } }
public string Address1 { get { return this.BasketResponse.deliverydata.add1; } }
public string PostCode { get { return this.BasketResponse.deliverydata.postcode; } }

public BasketToken Token { get; }

public dynamic BasketResponse { get; }
}


The BasketResponse contains more data that I will to interrogate later on (with a shed-load of TryParse,Try/Catch and Linq) so I do need to keep it. I also need to store it in a database - fortunately Cosmos DB can handle dynamics.



My questions are:




  1. Is this a sensible approach, using the dynamic object like one might use backing fields?

  2. Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?


I'm especially concerned about performance.





May be relevant:



Here is the SoapSimplifier



    internal class SoapSimplifier
{
private static XNamespace Xsi = "http://www.w3.org/2001/XMLSchema-instance";
private XElement ParsedResponse { get; set; }
private JObject ParsedJObject { get; set; }

public SoapSimplifier(string responseString)
{
this.ParsedResponse = XDocument.Parse(responseString).Descendants("return").First();
}

public JObject ToJObject()
{
if(this.ParsedJObject == null)
{
ParsedJObject = this.XElementToJObject(ParsedResponse);
}
return ParsedJObject;
}

public override string ToString()
{
return this.ToJObject().ToString();
}

private JObject XElementToJObject(XElement Item)
{
JObject jo = new JObject();
foreach (var i in Item.Elements("item"))
{
var valNode = i.Element("value");
if (valNode != null)
{
var nodeType = valNode.Attribute(Xsi + "type").Value;
if (nodeType == "xsd:string")
{
jo.Add(new JProperty(i.Element("key").Value, i.Element("value").Value));
}
else if (nodeType == "ns2:Map")
{
jo.Add(new JProperty(i.Element("key").Value, XElementToJObject(valNode)));
}
else if (nodeType == "SOAP-ENC:Array")
{
JArray ja = new JArray();
foreach (var node in valNode.Elements())
{
ja.Add(XElementToJObject(node));
}
jo.Add(new JProperty(i.Element("key").Value, ja));
}
}

}
return jo;
}
}


This takes the SOAP response generated from a PHP array sent via SOAP (similar to this one) and parses it into a JObject.



This is SOAP Jim, but not as we know it. The API provider will not supply a WSDL. Apart from a few guaranteed keys the array(s) returned could contain any number of key/value pairs and or other arrays.



As PHP arrays are dynamic, I can't think of a way of representing them in C# that isn't also dynamic.



I'm using jObject because it's fast and I can simultaneously create a readable JSON string for logging and a dynamic object that can be queried in c# with dot syntax.










share|improve this question




















  • 2




    I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
    – Flater
    Oct 31 '17 at 16:21










  • Well @Flater, you asked for it. I said it was horrible!
    – Jason Elkin
    Oct 31 '17 at 21:18















up vote
6
down vote

favorite












I have to interface with a horrible PHP SOAP API that returns nested arrays of strings. I've written a helper that can parse the SOAP response and return a dynamic object but I need at least some properties to be strongly typed.



The API returns a lot more data that I need to keep up front (but need to interrogate later) and apart from a few guaranteed fields, it is truly dynamic (it could contain pretty much anything).



I have created a proxy class that wraps the dynamic object like so:



public class Basket
{
public Basket(string basketResponse, BasketToken token)
{
this.Token = token;
this.BasketResponse = new SoapSimplifier(basketResponse).ToJObject();
}

public string FirstName { get { return this.BasketResponse.deliverydata.firstname; } }
public string LastName { get { return this.BasketResponse.deliverydata.lastname; } }
public string Tel { get { return this.BasketResponse.deliverydata.mobile; } }
public string Email { get { return this.BasketResponse.deliverydata.email; } }
public string Address1 { get { return this.BasketResponse.deliverydata.add1; } }
public string PostCode { get { return this.BasketResponse.deliverydata.postcode; } }

public BasketToken Token { get; }

public dynamic BasketResponse { get; }
}


The BasketResponse contains more data that I will to interrogate later on (with a shed-load of TryParse,Try/Catch and Linq) so I do need to keep it. I also need to store it in a database - fortunately Cosmos DB can handle dynamics.



My questions are:




  1. Is this a sensible approach, using the dynamic object like one might use backing fields?

  2. Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?


I'm especially concerned about performance.





May be relevant:



Here is the SoapSimplifier



    internal class SoapSimplifier
{
private static XNamespace Xsi = "http://www.w3.org/2001/XMLSchema-instance";
private XElement ParsedResponse { get; set; }
private JObject ParsedJObject { get; set; }

public SoapSimplifier(string responseString)
{
this.ParsedResponse = XDocument.Parse(responseString).Descendants("return").First();
}

public JObject ToJObject()
{
if(this.ParsedJObject == null)
{
ParsedJObject = this.XElementToJObject(ParsedResponse);
}
return ParsedJObject;
}

public override string ToString()
{
return this.ToJObject().ToString();
}

private JObject XElementToJObject(XElement Item)
{
JObject jo = new JObject();
foreach (var i in Item.Elements("item"))
{
var valNode = i.Element("value");
if (valNode != null)
{
var nodeType = valNode.Attribute(Xsi + "type").Value;
if (nodeType == "xsd:string")
{
jo.Add(new JProperty(i.Element("key").Value, i.Element("value").Value));
}
else if (nodeType == "ns2:Map")
{
jo.Add(new JProperty(i.Element("key").Value, XElementToJObject(valNode)));
}
else if (nodeType == "SOAP-ENC:Array")
{
JArray ja = new JArray();
foreach (var node in valNode.Elements())
{
ja.Add(XElementToJObject(node));
}
jo.Add(new JProperty(i.Element("key").Value, ja));
}
}

}
return jo;
}
}


This takes the SOAP response generated from a PHP array sent via SOAP (similar to this one) and parses it into a JObject.



This is SOAP Jim, but not as we know it. The API provider will not supply a WSDL. Apart from a few guaranteed keys the array(s) returned could contain any number of key/value pairs and or other arrays.



As PHP arrays are dynamic, I can't think of a way of representing them in C# that isn't also dynamic.



I'm using jObject because it's fast and I can simultaneously create a readable JSON string for logging and a dynamic object that can be queried in c# with dot syntax.










share|improve this question




















  • 2




    I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
    – Flater
    Oct 31 '17 at 16:21










  • Well @Flater, you asked for it. I said it was horrible!
    – Jason Elkin
    Oct 31 '17 at 21:18













up vote
6
down vote

favorite









up vote
6
down vote

favorite











I have to interface with a horrible PHP SOAP API that returns nested arrays of strings. I've written a helper that can parse the SOAP response and return a dynamic object but I need at least some properties to be strongly typed.



The API returns a lot more data that I need to keep up front (but need to interrogate later) and apart from a few guaranteed fields, it is truly dynamic (it could contain pretty much anything).



I have created a proxy class that wraps the dynamic object like so:



public class Basket
{
public Basket(string basketResponse, BasketToken token)
{
this.Token = token;
this.BasketResponse = new SoapSimplifier(basketResponse).ToJObject();
}

public string FirstName { get { return this.BasketResponse.deliverydata.firstname; } }
public string LastName { get { return this.BasketResponse.deliverydata.lastname; } }
public string Tel { get { return this.BasketResponse.deliverydata.mobile; } }
public string Email { get { return this.BasketResponse.deliverydata.email; } }
public string Address1 { get { return this.BasketResponse.deliverydata.add1; } }
public string PostCode { get { return this.BasketResponse.deliverydata.postcode; } }

public BasketToken Token { get; }

public dynamic BasketResponse { get; }
}


The BasketResponse contains more data that I will to interrogate later on (with a shed-load of TryParse,Try/Catch and Linq) so I do need to keep it. I also need to store it in a database - fortunately Cosmos DB can handle dynamics.



My questions are:




  1. Is this a sensible approach, using the dynamic object like one might use backing fields?

  2. Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?


I'm especially concerned about performance.





May be relevant:



Here is the SoapSimplifier



    internal class SoapSimplifier
{
private static XNamespace Xsi = "http://www.w3.org/2001/XMLSchema-instance";
private XElement ParsedResponse { get; set; }
private JObject ParsedJObject { get; set; }

public SoapSimplifier(string responseString)
{
this.ParsedResponse = XDocument.Parse(responseString).Descendants("return").First();
}

public JObject ToJObject()
{
if(this.ParsedJObject == null)
{
ParsedJObject = this.XElementToJObject(ParsedResponse);
}
return ParsedJObject;
}

public override string ToString()
{
return this.ToJObject().ToString();
}

private JObject XElementToJObject(XElement Item)
{
JObject jo = new JObject();
foreach (var i in Item.Elements("item"))
{
var valNode = i.Element("value");
if (valNode != null)
{
var nodeType = valNode.Attribute(Xsi + "type").Value;
if (nodeType == "xsd:string")
{
jo.Add(new JProperty(i.Element("key").Value, i.Element("value").Value));
}
else if (nodeType == "ns2:Map")
{
jo.Add(new JProperty(i.Element("key").Value, XElementToJObject(valNode)));
}
else if (nodeType == "SOAP-ENC:Array")
{
JArray ja = new JArray();
foreach (var node in valNode.Elements())
{
ja.Add(XElementToJObject(node));
}
jo.Add(new JProperty(i.Element("key").Value, ja));
}
}

}
return jo;
}
}


This takes the SOAP response generated from a PHP array sent via SOAP (similar to this one) and parses it into a JObject.



This is SOAP Jim, but not as we know it. The API provider will not supply a WSDL. Apart from a few guaranteed keys the array(s) returned could contain any number of key/value pairs and or other arrays.



As PHP arrays are dynamic, I can't think of a way of representing them in C# that isn't also dynamic.



I'm using jObject because it's fast and I can simultaneously create a readable JSON string for logging and a dynamic object that can be queried in c# with dot syntax.










share|improve this question















I have to interface with a horrible PHP SOAP API that returns nested arrays of strings. I've written a helper that can parse the SOAP response and return a dynamic object but I need at least some properties to be strongly typed.



The API returns a lot more data that I need to keep up front (but need to interrogate later) and apart from a few guaranteed fields, it is truly dynamic (it could contain pretty much anything).



I have created a proxy class that wraps the dynamic object like so:



public class Basket
{
public Basket(string basketResponse, BasketToken token)
{
this.Token = token;
this.BasketResponse = new SoapSimplifier(basketResponse).ToJObject();
}

public string FirstName { get { return this.BasketResponse.deliverydata.firstname; } }
public string LastName { get { return this.BasketResponse.deliverydata.lastname; } }
public string Tel { get { return this.BasketResponse.deliverydata.mobile; } }
public string Email { get { return this.BasketResponse.deliverydata.email; } }
public string Address1 { get { return this.BasketResponse.deliverydata.add1; } }
public string PostCode { get { return this.BasketResponse.deliverydata.postcode; } }

public BasketToken Token { get; }

public dynamic BasketResponse { get; }
}


The BasketResponse contains more data that I will to interrogate later on (with a shed-load of TryParse,Try/Catch and Linq) so I do need to keep it. I also need to store it in a database - fortunately Cosmos DB can handle dynamics.



My questions are:




  1. Is this a sensible approach, using the dynamic object like one might use backing fields?

  2. Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?


I'm especially concerned about performance.





May be relevant:



Here is the SoapSimplifier



    internal class SoapSimplifier
{
private static XNamespace Xsi = "http://www.w3.org/2001/XMLSchema-instance";
private XElement ParsedResponse { get; set; }
private JObject ParsedJObject { get; set; }

public SoapSimplifier(string responseString)
{
this.ParsedResponse = XDocument.Parse(responseString).Descendants("return").First();
}

public JObject ToJObject()
{
if(this.ParsedJObject == null)
{
ParsedJObject = this.XElementToJObject(ParsedResponse);
}
return ParsedJObject;
}

public override string ToString()
{
return this.ToJObject().ToString();
}

private JObject XElementToJObject(XElement Item)
{
JObject jo = new JObject();
foreach (var i in Item.Elements("item"))
{
var valNode = i.Element("value");
if (valNode != null)
{
var nodeType = valNode.Attribute(Xsi + "type").Value;
if (nodeType == "xsd:string")
{
jo.Add(new JProperty(i.Element("key").Value, i.Element("value").Value));
}
else if (nodeType == "ns2:Map")
{
jo.Add(new JProperty(i.Element("key").Value, XElementToJObject(valNode)));
}
else if (nodeType == "SOAP-ENC:Array")
{
JArray ja = new JArray();
foreach (var node in valNode.Elements())
{
ja.Add(XElementToJObject(node));
}
jo.Add(new JProperty(i.Element("key").Value, ja));
}
}

}
return jo;
}
}


This takes the SOAP response generated from a PHP array sent via SOAP (similar to this one) and parses it into a JObject.



This is SOAP Jim, but not as we know it. The API provider will not supply a WSDL. Apart from a few guaranteed keys the array(s) returned could contain any number of key/value pairs and or other arrays.



As PHP arrays are dynamic, I can't think of a way of representing them in C# that isn't also dynamic.



I'm using jObject because it's fast and I can simultaneously create a readable JSON string for logging and a dynamic object that can be queried in c# with dot syntax.







c# xml wrapper soap






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 1 '17 at 9:05

























asked Oct 31 '17 at 12:13









Jason Elkin

1314




1314








  • 2




    I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
    – Flater
    Oct 31 '17 at 16:21










  • Well @Flater, you asked for it. I said it was horrible!
    – Jason Elkin
    Oct 31 '17 at 21:18














  • 2




    I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
    – Flater
    Oct 31 '17 at 16:21










  • Well @Flater, you asked for it. I said it was horrible!
    – Jason Elkin
    Oct 31 '17 at 21:18








2




2




I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
– Flater
Oct 31 '17 at 16:21




I'm struggling to find a reason for using dynamic here. Can you post the code from the SoapSimplifier constructor? Maybe I'm missing something about what exactly it's trying to achieve.
– Flater
Oct 31 '17 at 16:21












Well @Flater, you asked for it. I said it was horrible!
– Jason Elkin
Oct 31 '17 at 21:18




Well @Flater, you asked for it. I said it was horrible!
– Jason Elkin
Oct 31 '17 at 21:18










1 Answer
1






active

oldest

votes

















up vote
0
down vote













The answer to your second question...




Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?




Is yes.



You're fetching the data, so set it in the constructor, that way, you're doing the work in one place.



Is there a need to use the BasketResponse Property again. Aren't you mapping all the data you need already?






share|improve this answer





















  • Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
    – Jason Elkin
    Nov 1 '17 at 8:55











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f179252%2fproxy-wrapper-class-for-a-dynamic-object-from-a-soap-api%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote













The answer to your second question...




Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?




Is yes.



You're fetching the data, so set it in the constructor, that way, you're doing the work in one place.



Is there a need to use the BasketResponse Property again. Aren't you mapping all the data you need already?






share|improve this answer





















  • Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
    – Jason Elkin
    Nov 1 '17 at 8:55















up vote
0
down vote













The answer to your second question...




Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?




Is yes.



You're fetching the data, so set it in the constructor, that way, you're doing the work in one place.



Is there a need to use the BasketResponse Property again. Aren't you mapping all the data you need already?






share|improve this answer





















  • Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
    – Jason Elkin
    Nov 1 '17 at 8:55













up vote
0
down vote










up vote
0
down vote









The answer to your second question...




Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?




Is yes.



You're fetching the data, so set it in the constructor, that way, you're doing the work in one place.



Is there a need to use the BasketResponse Property again. Aren't you mapping all the data you need already?






share|improve this answer












The answer to your second question...




Would it be better to interrogate the dynamic BasketResponse in the constructor and set the values of the properties when basket is instantiated?




Is yes.



You're fetching the data, so set it in the constructor, that way, you're doing the work in one place.



Is there a need to use the BasketResponse Property again. Aren't you mapping all the data you need already?







share|improve this answer












share|improve this answer



share|improve this answer










answered Oct 31 '17 at 21:42









mrdnk

1265




1265












  • Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
    – Jason Elkin
    Nov 1 '17 at 8:55


















  • Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
    – Jason Elkin
    Nov 1 '17 at 8:55
















Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
– Jason Elkin
Nov 1 '17 at 8:55




Yes, I need to keep hold of BasketResponse. My instinct was to set values in the constructor but that means that I am duping the data. My (limited) understanding of dynamics suggests that this would also force the compiler to evaluate the dynamic objects/properties when the class is constructed, whether or not a property is actually used. Wrapping them in the getter makes them lazy which seems more efficient.
– Jason Elkin
Nov 1 '17 at 8:55


















draft saved

draft discarded




















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f179252%2fproxy-wrapper-class-for-a-dynamic-object-from-a-soap-api%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Сан-Квентин

8-я гвардейская общевойсковая армия

Алькесар