Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting Values from an Array into a SOAP Message based on Key

In an ASP.NET application in which users ("User A") can set up their own web service connections using SOAP, I let them insert their own envelope, which, for example, could be something along these lines:

//Formatted for Clarity
string soapMessage = 
"<soap: Envelope //StandardStuff>
  <soap:Header //StandardStuff>
    <wsse:UsernameToken>
      <wsse: Username>{F1}</wsse:Username>
      <wsse: Password Type''>{F2}</wsse:Password>  
    </wsse:UsernameToken>
  </soap:Header>
  <soap:Body>
    <ref:GetStuff>
      <ref:IsActive>{F3}</ref:IsActive>
    </ref:GetStuff>
  </soap:Body>
</soap:Envelope>"

At the same time I a "User B" that sends an array of data, passed down from Javascript as json that looks a little something like this:

[
  { 
    key: "F1", 
    value: "A" 
  },
  { 
    key: "F2", 
    value: "B" 
  },
  { 
    key: "F3", 
    value: "C" 
  }
];

This array enters the fray as a string before being deserialized (dynamic JsonObject = JsonConvert.DeserializeObject(stringifiedJson);).

Now, I would like to be able to insert the corresponding values into the envelope, preferably with a degree of security that won't allow people to do funky stuff by inserting weird values in the array (a regex would probably be my last resort).

So far I'm aware of the concept to build the string like so (With the {}'s in the soap message being replaced by {0}, {1} & {2}):

string value1 = "A";
string value2 = "B";
string value3 = "C";
var body = string.Format(@soapMessage, value1, value2, value3);

request.ContentType = "application/soap+xml; charset=utf-8";
request.ContentLength = body.Length;
request.Accept = "text/xml";
request.GetRequestStream().Write(Encoding.UTF8.GetBytes(body), 0, body.Length);

But the amount of values in this array as well as the might change according to the user's input as well as a shifting order of references, so I need something more flexible. I'm very new to making SOAP calls, so as dumb an answer as possible would be appreciated.

like image 631
Patrick Avatar asked Oct 30 '22 00:10

Patrick


2 Answers

Consider creating a function that would replace the placeholders with their respective values.

private string FormatMessage(string soapMessage, IDictionary<string, string> parameters) {
    var message = soapMessage;
    foreach (var kvp in parameters) {
        var placeholder = "{" + kvp.Key + "}";
        if (message.IndexOf(placeholder) > -1) {
            message = message.Replace(placeholder, kvp.Value);
        }
    }
    return message;
}

Where the dictionary was extracted from JSON supplied to the function.

var parameters = JsonConvert.DeserializeObject<IDictionary<string, string>>(json);

string body = FormatMessage(soapMessage, parameters);

You would however need to validate the values and keys provided to avoid injections that could adversely affect your system.

like image 92
Nkosi Avatar answered Nov 15 '22 06:11

Nkosi


It is always a good idea to process xml using xml processors instead of string replacement. My cross-thinking idea might not exactly fit your usecase, i didnt get your big picture 100% i have to admit.

Anyway my Answer is that you could use xpaths as key which would enable you to utilize xml processing tools on the backend. You do not neccessarily have to validate anything at this point, this is very dependent on the architecture.

So in my mind, javascript provides this structure:

[
  { 
    key: "//family-name", 
    value: "Michael" 
  },
  { 
    key: "//nickname", 
    value: "Jackson" 
  }
];

And the backend:

XmlElement foo = (XmlElement)doc.SelectSingleNode(key);
foo.InnerText = value;
like image 27
Harry Avatar answered Nov 15 '22 04:11

Harry