RestSharp to edit one element of xml file - c#

For the documentation of the API I am using, the instructions are:
To edit an existing resource: GET the full XML file for the resource you want to change (/api/customers/7), edit its content as needed, then PUT the whole XML file back to the same URL again.
Now my question is, if I only want to edit one element (out of many) in XML file, is there any function in RestSharp to allow me to only edit that single element, without deserializing the entire XML?
As an example, my XML:
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<customer>
<id><![CDATA[1]]></id>
<id_default_group xlink:href="http://heatherfazelinia.com/api/groups/3"><![CDATA[3]]></id_default_group>
<id_lang xlink:href="http://heatherfazelinia.com/api/languages/1"><![CDATA[1]]></id_lang>
<newsletter_date_add><![CDATA[2013-12-13 08:19:15]]></newsletter_date_add>
<ip_registration_newsletter></ip_registration_newsletter>
<last_passwd_gen><![CDATA[2014-06-20 16:56:30]]></last_passwd_gen>
<secure_key><![CDATA[6a9b9eab95448d74a026b869d8cd723e]]></secure_key>
<deleted><![CDATA[0]]></deleted>
<passwd><![CDATA[6028853eb1033578f7432015042fa486]]></passwd>
<lastname><![CDATA[DOE]]></lastname>
<firstname><![CDATA[John]]></firstname>
<email><![CDATA[pub#prestashop.com]]></email>
<id_gender><![CDATA[1]]></id_gender>
<birthday><![CDATA[1970-01-15]]></birthday>
<newsletter><![CDATA[1]]></newsletter>
<optin><![CDATA[1]]></optin>
<website></website>
<company></company>
<siret></siret>
<ape></ape>
<outstanding_allow_amount><![CDATA[0.000000]]></outstanding_allow_amount>
<show_public_prices><![CDATA[0]]></show_public_prices>
<id_risk><![CDATA[0]]></id_risk>
<max_payment_days><![CDATA[0]]></max_payment_days>
<active><![CDATA[1]]></active>
<note></note>
<is_guest><![CDATA[0]]></is_guest>
<id_shop><![CDATA[1]]></id_shop>
<id_shop_group><![CDATA[1]]></id_shop_group>
<date_add><![CDATA[2014-08-01 13:20:37]]></date_add>
<date_upd><![CDATA[2014-08-01 13:20:37]]></date_upd>
<associations>
<groups node_type="group">
<group xlink:href="http://heatherfazelinia.com/api/groups/3">
<id><![CDATA[3]]></id>
</group>
</groups>
</associations>
</customer>
</prestashop>
I have figured out how to deserialize specific values, for example: "firstname" and "lastname".
But my current question is specifically: If I wanted to only edit "firstname" of that XML with a PUT request, would I need to deserialize and edit the entire XML? Or is there any function in RestSharp to help with that, where I can directly have it edit only the "firstname" element?
Thanks

RestSharp isn't an serialization / deserialization framework. Its a "Simple REST and HTTP API Client for .NET". It does come with an out-of-the-box features such as deserializing xml / json into proper objects (using a 3rd party framework like Json.NET).
Therefore, it cant do what you're asking, you'll have to deserialize the whole xml and change the attributes you desire.
What you need to be done can be done quite easily using LINQ 2 XML:
//Assuming you get your xml as a string:
var xml = XElement.Load(yourXmlString);
var firstName = xml.Element("customer").Element("firstname");
var lastName = xml.Element("customer").Element("lastname");
firstName.Value = "firstChange";
lastName.Value = "secondChange";
var returnedXml = xml.ToString();
Of course, you'll have to add nullity checks, exception handling, etc.

Related

C# SOAP client: sending generic XmlNode request

I have a C# project where I added a SOAP service reference, using the integrated visual studio functionality (right click -> add -> service reference)
The client classes are generated correctly without errors. However, the various methods of the service only accept a generic System.Xml.XmlNode as an input, rather than a structured object.
This should not be a problem in theory, since I have the complete XML file with the query that I need to perform. So I tried doing it like this:
NSIStdV20ServiceSoapClient client = new NSIStdV20ServiceSoapClient();
var getAllDataFlowQuery = File.ReadAllText(#"Query\get_all_dataflow.xml"); //file containing the query
XmlDocument doc = new XmlDocument();
doc.LoadXml(getAllDataFlowQuery);
var dataStructures = client.QueryStructure(doc); //this method accepts a System.Xml.XmlNode as parameter
However, this doesn't work, throwing
System.ServiceModel.FaultException: 'Error due to a non correct client message'
I thought initially that the query was incorrect, but I tried to perform the exact same query using SoapUI and it works perfectly! I even tried doing it with the exact XML returned by doc.InnerXml (just to be sure che XmlDocument object was not modifying the XML) and it works.
So basically it's only when calling the method from C# that it doesn't work.
If you want to try it out yourself, the service is freely accessible, the WSDL is here:
http://sdmx.istat.it/SDMXWS/NsiStdV20Service.asmx?WSDL
and you should try to call the QueryStructure method with the following payload:
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://ec.europa.eu/eurostat/sri/service/2.0"><soapenv:Header /><soapenv:Body><web:QueryStructure><!--Optional:--><web:Query><RegistryInterface xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message SDMXMessage.xsd" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:compact="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/compact" xmlns:cross="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/cross" xmlns:generic="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:query="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query" xmlns:structure="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure" xmlns:registry="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/registry" xmlns:utility="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/utility" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Header><ID>JD014</ID><Test>true</Test><Truncated>false</Truncated><Name xml:lang="en">Trans46302</Name><Prepared>2001-03-11T09:30:47-05:00</Prepared><Sender id="BIS" /></Header><QueryStructureRequest resolveReferences="false"><registry:DataflowRef /></QueryStructureRequest></RegistryInterface></web:Query></web:QueryStructure></soapenv:Body></soapenv:Envelope>
As I said, this works perfectly in SoapUI, but doesn't work when calling the client method from C#
Well, it seems that the client generated by visual studio, even tho it accepts a XmlNode as input, creates some of the required outer structure itself (to be precise: all the outer nodes with the soapenv and web namespaces).
Which means I had to strip down the input XML to:
<?xml version="1.0" encoding="UTF-8"?><RegistryInterface xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message SDMXMessage.xsd" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:compact="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/compact" xmlns:cross="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/cross" xmlns:generic="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:query="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query" xmlns:structure="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/structure" xmlns:registry="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/registry" xmlns:utility="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/utility" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Header><ID>JD014</ID><Test>true</Test><Truncated>false</Truncated><Name xml:lang="en">Trans46302</Name><Prepared>2001-03-11T09:30:47-05:00</Prepared><Sender id="BIS" /></Header><QueryStructureRequest resolveReferences="false"><registry:DataflowRef /></QueryStructureRequest></RegistryInterface>

I Getting null Response From sabre service GetReservation

I am getting null response from sabre web service when call GetReservation Request
<GetReservationRQ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.18.0">
<Locator xmlns="http://webservices.sabre.com/pnrbuilder/v1_18">Its Unique </Locator>
<RequestType xmlns="http://webservices.sabre.com/pnrbuilder/v1_18">Stateful</RequestType>
<ReturnOptions xsi:type="ReturnOptions" xmlns="http://webservices.sabre.com/pnrbuilder/v1_18">
<ViewName>VaDefaultWithPq</ViewName>
</ReturnOptions>
</GetReservationRQ>
in this ReturnOptions tag one more element is missing is ResponseFormate that default value is STL so thats why it can not show on xml writing.
Is there a reason you are using "It's Unique" as a record locator? You should put a valid record locator there or delete the node if you are reading a PNR you have in your work area.
Can you post the Sabre endpoint you are pointing your application to?

How to validate XML with generated c# class from XSD

I want to send a http request from client to local server and on the server I made a query with Linq that returns data in xml
I also have .xsd file and a .cs file enerated from my xsd file that I want to validate my xml with.
I have several questions:
how can I validate xml with c# generated class?
how can I return xml from server to client?
http://www.codeproject.com/Questions/898525/How-to-validate-XML-with-generated-csharp-class-fr
Thanks
Well, I see two separate questions, so I'll provide two separate answers:
1.) How can I validate XML [with a C# generated class]
The answer actually doesn't involve the C# generated class at all. Once you've validated the XML, you can deserialize it into your autogenerated class; however, validating XML against a schema doesn't require it. To validate XML against a known schema (assuming you have a XSD file), you can do the following:
// define your schema set by importing your schema from an xsd file
var schemaSet = new XmlSchemaSet();
var schema = XmlReader.Create("D:\myschema.xsd");
schemaSet.Add(null, schema);
schemaSet.Compile();
// your schema defines several types. Your incoming XML is (presumably) expected to of one of these types (e.g. type="_flashList")
// whatever the expected type is of the XML document root, use that string here to grab information about that type from the schema
var partialSchemaObject = schemaSet.GlobalTypes[new XmlQualifiedName("_flashList")];
// go get your xml, then validate!
// here, SchemaValidationEventHandler is a delegate that is called for every validation error or warning
var myXml = GoGetMyXmlIWantToValidate() as XDocument;
myXml.Root.Validate(partialSchemaObject, schemaSet, SchemaValidationEventHandler, true);
2.) How can I return XML from server to client?
You can use the 'StringContent' type for your HttpContent
var myResponseXml = GoGetMyResponseXml() as XElement;
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
// specify string content, with UTF8 encoding, with a content-type of application/xml
Content = new StringContent(myResponseXml.ToString(), Encoding.UTF8, "application/xml");
};

Envelop tag missing in xml object

I have a web application where the users can upload a specific XML file, then i need to convert the XML file to a object which is expect in a webservice.
Code:
var document = new XmlDocument();
document.Load(#"C:\Desktop\CteWebservice.xml");
var serializer =new XmlSerializer(typeof(OCTE));
var octe = (OCTE)serializer.Deserialize(new StringReader(document.OuterXml));
var serviceClient = new WSServiceClient();
serviceClient.InsertOCTE(octe);
I get this error when i try to deserialize the xml document as a OCTE object:
< Envelope xmlns='http://schemas.xmlsoap.org/soap/envelope/'> was not expect.
Obvious, the OCTE class doesn't have a Envelope property.
My question is, i need to include this tag in the OCTE class or i need to do something else in the client?
I can think of at least two different solutions to your problem, which seems to be caused by the fact that the XML file contain the full SOAP request, which will contain a SOAP Envelope, a SOAP Body element and potentially a SOAP header element.
The structure of SOAP body element is dependent on the SOAP Binding style, which most likely will be Document Literal Wrapped - for further details look at http://www.ibm.com/developerworks/webservices/library/ws-usagewsdl/index.html?ca=dat-
This means that the OCTE structure that you are looking for, might be embedded inside a request element, something like (document literal wrapped SOAP binding style)
<soap:envelope>
</soap:header>
<soap:body>
<insertOCTERequest>
<OCTE>
...
</OCTE>
</insertOCTERequest>
</soap:body>
</soap:envelope>
So to the possible solutions
Ensure that the CteWebService.xml is serialised to have the OCTE structure as it's root element.
Use etc. XPath to locate the OCTE element, and deserialise that instead.
var nsmgr = ...
var element = document.SelectSingleNode("//OCTE", nsmgr);
You only need to initialise a Xml NamespaceManager if the OCTE element belongs to a specified xml namespace, otherwise you can leave it out.

How to retrieve a collection out of an SOAP message

I'm using a webservice for render company information based on a special company number.
But i can not get data out of the response SOAP message.
You can see an example of the response soap message. (I left out some company information the tags).
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<businessGetDossierV3Response xmlns="http://www.webservices.nl/soap/">
<out>
<paging>
<curpage>1</curpage>
<perpage>10</perpage>
<numpages>1</numpages>
<numresults>1</numresults>
<maxresults>100</maxresults>
</paging>
<results>
<item>
<DossierNo></DossierNo>
<SubDossierNo></SubDossierNo>
<ChamberNo></ChamberNo>
<Legalformcode></Legalformcode>
<LegalformcodeText></LegalformcodeText>
<Tradename45></Tradename45>
<EstablishmentPostcode></EstablishmentPostcode>
<EstablishmentCity></EstablishmentCity>
<EstablishmentStreetname></EstablishmentStreetname>
<EstablishmentHouseNo></EstablishmentHouseNo>
<CorrespondencePostcode></CorrespondencePostcode>
<CorrespondenceCity></CorrespondenceCity>
<CorrespondenceStreetname></CorrespondenceStreetname>
<CorrespondenceHouseNo></CorrespondenceHouseNo>
</item>
</results>
</out>
</businessGetDossierV3Response>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
! this is the result i see on the demo client !
But this is my code in C#
nl.webservices.ws1.BusinessDossierV3PagedResult result = null;
result = myserviceBusiness.businessGetDossierV3(KVKnr, "0000", 1);
I want to do something like this (but with the results instead of paging part)
int page = result.paging.numpages;
Then I should be like this I suppose
string city = result.results.item.CorrespondenceCity;
But this is giving a fault message
So in Visual studio 2010, i can only retrieve the data in the paging part of the xml and put it into a textbox, but not from results part. Is this because the result part is some kind of Collection?
So yes, how can i put the data from the tags EstablishmentPostcode and EstablishmentCity in a textbox on my default page?
thanks in advance
You could try adding your SOAP service as a web reference to the project. http://msdn.microsoft.com/en-us/library/tydxdyw9.aspx
If you don't want to do this and would rather work on the XML directly you could use xpath to get access to all the item elements in your results element.
http://www.stardeveloper.com/articles/display.html?article=2009031001&page=1
One thing to be careful of when using xpath is that you use the correct xml namespace for the node you're trying to select.
Ben

Categories