2017-10-19 116 views
5

W aplikacji ASP.NET, w której użytkownicy ("Użytkownik A") mogą konfigurować własne połączenia usług WWW przy użyciu protokołu SOAP, pozwalam im wstawiać własne koperty, które na przykład, może być coś wzdłuż tych linii:Wstawianie wartości z tablicy do komunikatu SOAP na podstawie klucza

//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>" 

Jednocześnie I a „User B”, który wysyła tablicę danych, przekazywane z JavaScript jak JSON, który wygląda trochę coś takiego:

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

Ta tablica wprowadza próbkę jako ciąg przed deserializacją (dynamic JsonObject = JsonConvert.DeserializeObject(stringifiedJson);).

Teraz chciałbym móc wstawić odpowiednie wartości do koperty, najlepiej z pewnym stopniem bezpieczeństwa, który nie pozwoli ludziom robić fajnych rzeczy przez wstawianie dziwnych wartości w tablicy (regex prawdopodobnie byłby moja ostatnia deska ratunku).

tej pory jestem świadomy koncepcji zbudować ciąg jak tak (z {} JEST W komunikacie mydła zastępowane przez {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); 

ale ilość wartości w tej tablicy jak również moc może się zmieniać w zależności od danych wprowadzanych przez użytkownika, a także od zmiany kolejności referencji, więc potrzebuję czegoś bardziej elastycznego. Jestem bardzo nowy w nawiązywaniu połączeń SOAP, więc doceniłbym głupią odpowiedź.

+0

Czy oceniłeś już istniejące silniki szablonowe, takie jak 'nustache' (https://github.com/jdiamond/Nustache) lub' handlebars.net' (https://github.com/rexm/Handlebars.Net)? –

+0

Nie mam, ponieważ nie mam prawa dodawać nowych bibliotek do tego projektu. Jako taka opcja, w której nie są one wymagane, miałaby pierwszeństwo. – Patrick

Odpowiedz

1

Rozważ utworzenie funkcji, która zastąpi symbole zastępcze odpowiednimi wartościami.

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; 
} 

Gdzie słownik został wyodrębniony z JSON dostarczonego do funkcji.

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

string body = FormatMessage(soapMessage, parameters); 

Należy jednak sprawdzić poprawność podanych wartości i kluczy, aby uniknąć wstrzyknięć, które mogą niekorzystnie wpłynąć na system.

+0

Czy są jakieś sugestie dotyczące sprawdzania poprawności tych wartości? Problem polega na tym, że dotyczy to jednego użytkownika dostarczającego wiadomość do wypełnienia przez innego użytkownika, więc nie ma wcześniejszej wiedzy na temat tego, co ten komunikat lub wartości mogą zawierać. – Patrick

+0

@Patrick, Są to problemy związane z implementacją, które należy rozwiązać przed przekształceniem wiadomości. A ponieważ masz kontrolę nad kodem, zawsze możesz sprawdzić, czy podane wartości pasują do bieżącego użytkownika, zanim spróbujesz go przekształcić. – Nkosi

1

Zawsze dobrym pomysłem jest przetwarzanie xml przy użyciu procesorów xml zamiast zamiany ciągów znaków. Moja myśl krzyżowa może nie pasować do Twojego przypadku, nie dostaję twojego pełnego obrazu, który muszę przyznać w 100%.

W każdym razie, moja odpowiedź brzmi, że można użyć xpaths jako klucza, który umożliwi korzystanie z narzędzi przetwarzania xml na zapleczu. W tym momencie nie musisz niczego sprawdzać, jest to bardzo zależne od architektury.

Więc w moim umyśle, javascript zapewnia tę strukturę:

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

a backend:

XmlElement foo = (XmlElement)doc.SelectSingleNode(key); 
foo.InnerText = value; 
+0

Chodzi o to, że wiadomość mydlana jest dostarczana przez użytkownika A, a wartości są dostarczane przez użytkownika B, ponieważ może to być skomplikowane, aby użytkownik A pomyślał w selektorach xml, ale ja absolutnie kocham twoje wyjście poza -boxowy pomysł. – Patrick

0

Najlepszym narzędziem do tego zadania, IMHO, jest XSLT:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:crs="CRS610MI" exclude-result-prefixes="crs"> 
<xsl:output method="xml"/> 
<xsl:template match="/"> 
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
    <soap:Body> 
    <xsl:apply-templates select="node()|@*"/> 
    </soap:Body> 
    </soap:Envelope> 
</xsl:template> 
<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

Istnieje stanowisko na SO dotyczące tego tematu:

Wrap XML in SOAP envelope in .net

. NET Obsługuje XSLT po wyjęciu z pudełka, więc nie potrzebujesz żadnych bibliotek zewnętrznych.Chciałbym załadować JSON do obiektu XML i zastosować go do szablonu XSLT, który zmodyfikujesz, aby uszanować twoją strukturę XML w pamięci.

Użyj XmlLoader w C#, aby załadować JSON do obiektu XML:

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xml); 
string jsonText = JsonConvert.SerializeXmlNode(doc); 

// To convert JSON text contained in string json into an XML node 
XmlDocument doc = JsonConvert.DeserializeXmlNode(json); 

ładowania szablonu XSLT w .NET jest dość prosta:

var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas())); 

Jest to czysty i profesjonalny podejście, które moim zdaniem pasuje do twoich kryteriów.