Connecting to SalesForce bulk API using C# - c#

I am trying to connect to the SalesForce.com bulk API so I can do mass uploads of data from my application. I have read through the PDF documentation which emphasizes using CURL to make the POST requests. In keeping with the instructions, I have created a text file in XML format which is used for logging into the server.
Login.txt contents below:
<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:login xmlns:n1="urn:partner.soap.sforce.com">
<n1:username>my username</n1:username>
<n1:password>my password</n1:password>
</n1:login>
</env:Body>
</env:Envelope>
Here is what I'm trying to do in my code to make the login request:
XmlDocument XMLResponse = null;
HttpWebRequest httpRequest;
HttpWebResponse httpResponse = null;
Stream requestStream = null;
Stream responseStream = null;
XmlTextReader xmlReader;
httpRequest = HttpWebRequest)WebRequest.Create("https://login.salesforce.com/services/Soap/c/20.0");
try
{
byte[] bytes = File.ReadAllBytes(filename);
httpRequest.Method = "POST";
httpRequest.ContentLength = bytes.Length;
httpRequest.ContentType = "text/xml; charset=UTF-8";
httpRequest.Headers.Add("SOAPAction: login");
requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
responseStream = httpResponse.GetResponseStream();
xmlReader = new XmlTextReader(responseStream);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xmlReader);
XMLResponse = xmldoc;
xmlReader.Close();
}
httpResponse.Close();
}
When this code executes I always get a 500 error. Does anyone have any experience in doing what I am attempting to do? Could you please provide me with some suggestions?
Thank you in advance.

For the login part, just download and import the partner WSDL and use the generated web service client. Otherwise, you'll want to update your code to read the response when it gets a 500 status code (the SOAP spec requires fault messages to use a 500 status code), the response body will give you more clues to the problem. I'd expect in this case you're getting an identity confirmation error, and you'll need to provide your api security token in addition to your password in the login request.

Generate the XML file to salesforce login
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<login xmlns="urn:enterprise.soap.sforce.com">
<username>username</username>
<password>password + token</password>
</login>
</soap:Body>
</soap:Envelope>
use the following c# code for login to salesforce
XmlDocument doc = new XmlDocument();
doc.LoadXml(str);
string uri = "https://login.salesforce.com/services/Soap/c/21.0";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Headers.Add("SOAPAction", "login");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
stm = req.GetRequestStream();
doc.Save(stm);
stm.Close();
WebResponse resp = req.GetResponse();
stm = resp.GetResponseStream();
XmlDocument doc1 = new XmlDocument();
doc1.Load(stm);

Related

Is it possible to consume an XML RPC service using a basic HTTP request?

I've been tasked to consume an XML RPC API, and I'm quite unfamiliar with it. I've glanced around a few pages describing it, and I've seen there's a few libraries out there as well.
However, it's left me with a feeling that all it comes down to is posting an HTTP request, similar to REST, except using XML in the body as opposed to JSON.
I imagine constructing an HTTP request similar to the below:
POST /path/service.cfm HTTP/1.0
From: example#example.com
User-Agent: whatever/1.0
Content-Type: application/xml
Content-Length: 155
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>40</i4></value>
</param>
</params>
</methodCall>
Am I on the right track? The abundance of libraries around give me the feeling that perhaps it's more complicated than what I thought. Ideally I'd like to write a quick client in .NET myself.
static void Main(string[] args)
{
HttpWebRequest request = BuildWebRequest();
var response = request.GetResponse() as HttpWebResponse;
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
private static HttpWebRequest BuildWebRequest()
{
var request = WebRequest.Create(Url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/xml";
request.Timeout = 40000;
request.ServicePoint.Expect100Continue = true;
string body = #"<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>40</i4></value>
</param>
</params>
</methodCall>";
byte[] bytes = Encoding.Default.GetBytes(body);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
return request;
}
Yes it is not a problem, here is an example how to do it. In string body you must write only your xml and you should put the correct content type. If the service provider have requirements like specific Headers you should add them.

Throwing a WebException while posting XML data using HttpWebRequest and HttpWebrequest in c#

I am trying to get a response xml from the UIDAI data centers by sending an xml document using HttpWebRequest and receiving it using HttpWebResponse in C#ASP.net web based application. I already checked it using a java application and it is working fine on their side but the web based application is throwing an exception
An exception of type 'System.Net.WebException' occurred in System.dll but was not handled in user code
Note:The web exception occurs on the 5th line from the last
Please suggest some methods to resolve this
public void SendForAuthentication()//user defined function for Sending and Receiving Requests
{
string url = "http://auth.uidai.gov.in/1.6/public/9/9/MLTbKYcsgYMq1zgL3WMZYrnyvsarlljxpom2A-QTPc0Zud23shpnqPk";//the host address
StreamReader sr1 = new StreamReader("D:\\test-signed.xml");//loading xml file to stream
string XMLData = sr1.ReadToEnd();
string Conn = #"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>";
XMLData = Conn + XMLData;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(XMLData);
req.Method = "POST";
req.ContentType = "text/xml;charset=utf-8";
req.ContentLength = requestBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();//**here I am getting a webexception**
StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);
string backstr = sr.ReadToEnd();
reader.ReadToFollowing("title");
File.WriteAllText("D:\\xml.xml", backstr);
}
edit:
The exception I get is "the operation has timed out" though I had increased the operation time
edit2:
The above code works fine there was actually a problem with my firewall

ContentMD5Missing - Amazon Webservice

I'm trying to post to Feed -> SubmitFeed.
However the exception I receive back is:
you must pass a Content-MD5 HTTP header for your feed so we can be
sure it was not corrupted (e.g. dropped a 0 from a price) before we
process it
What I don't understand is the documentation states that it is optional so unsure why I am receiving this. Plus I am actually passing something through.
XML
<?xml version="1.0" encoding="UTF-8" ?>
- <AmazonEnvelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" schemaLocation="amzn-base.xsd">
- <Header>
<DocumentVersion>1</DocumentVersion>
<MerchantIdentifier>A1ddWU5JfffWJEddV9Xf668B</MerchantIdentifier>
</Header>
<MessageType>Product</MessageType>
<PurgeAndReplace>false</PurgeAndReplace>
- <Message>
<MessageId>1</MessageId>
<OperationType>Update</OperationType>
</Message>
- <Product>
<SKU>3308ff6-01</SKU>
</Product>
</AmazonEnvelope>
How I attach the Body/Header
var request = Helper.CreateWebRequest(xmlRequest.Config, genericparameters, signatureHelpers);
request.Headers.Add("x-amazon-user-agent", amazonHostAgent);
request.Method = "POST";
request.ContentType = amazonConfig.ContentType;
request.Timeout = 50000;
Helper.AddXmlDocumentToRequest(xmlRequest.XmlDocument.InnerXml, request);
public static void AddXmlDocumentToRequest(string xmlDocument, WebRequest request)
{
var bytes = Encoding.ASCII.GetBytes(xmlDocument);
request.ContentLength = bytes.Length;
var requestStream = request.GetRequestStream();
request.Headers.Add("Content-MD5", GetMd5HashFromStream(bytes));
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
}
public static string GetMd5HashFromStream(byte[] bytes)
{
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
}
Within the request when I drill down to Headers I have the following:
{x-amazon-user-agent: MWSApplication/1.0 (Language=c#)
Content-Type: text/xml
Host: mws.amazonservices.co.uk
Content-Length: 478
Expect: 100-continue
Content-MD5: 1xLxj5Y+WVsAVR9BbQfzQA==
}
When I run the xml through scratchpad it returns the same Content-MD5: 1xLxj5Y+WVsAVR9BbQfzQA==
Am I doing something wrong?
Thanks,
Clare
This might not be the answer for everyone however it was for me and if it helps one other person I will be happy :-)
Me being very stupid, added the header after the streaming, this is not what you should be doing.
Create the URL
Add headers and other elements i.e.
request.ContentType
Stream documents (body of request) if required
request.GetResponse.
Thanks,
Clare

Soap Request in C#

I've got a soap request I've written in http & javascript but I cannot seem to convert it into C# correctly.
Original: (Works)
<button onclick="doStuff()" type="submit">Send</button>
<textarea name="REQUEST_DATA" cols=120 rows=17 >
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<createModifyRequest>
<username>josephs</username>
<lookupIds>
<lookupIds>4225</lookupIds><!--firepass-->
</lookupIds>
</createModifyRequest>
</soap:Body>
</soap:Envelope>
</textarea>
<script language="javascript">
function doStuff() {
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
xmlhttp.open("POST", "http://tpdev-itreq.transpower.co.nz:7777/usr/services/CreateModifyRequest", false);
xmlhttp.setRequestHeader("SOAPAction", "createModifyRequest");
var userpass = "josephs" + ":" + "pass";
xmlhttp.setRequestHeader("Authorization", "Basic " + (userpass));
xmlhttp.setRequestHeader("Content-Type", "text/xml");
xmlhttp.send(REQUEST_DATA.value);
}
Converted in C# (Does not work)
private void button1_Click(object sender, EventArgs e)
{
string soap =#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<createModifyRequest>
<username>josephs</username>
<lookupIds>
<lookupIds>4225</lookupIds>
<!--firepass-->
</lookupIds>
</createModifyRequest>
</soap:Body>
</soap:Envelope>";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://tpdev-itreq.transpower.co.nz:7777/usr/services/CreateModifyRequest");
req.Headers.Add("SOAPAction", "\"createModifyRequest\"");
var userpass = "josephs" + ":" + "pass";
req.Headers.Add("Authorization", "Basic " + (userpass));
// req.Headers.Add("Content-Type", "text/xml");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse response = req.GetResponse();
Stream responseStream = response.GetResponseStream();
// TODO: Do whatever you need with the response
}
At the moment when I run the C# code I get an internal 500 server error, so what have I done wrong?
I have tried to reproduce your problem. Currently i am not able to create your request but i have generated local request with your data.
One thing I came to know is if I remove double quotes(") around the utf-8 and it worked fine.
Just pass charset=utf-8 instead of charset=\"utf-8\""
I am not sure it will work for you or not.
Is there a reason you can't just use Visual Studio's built in support for SOAP web services?
You can add a service reference or a web reference (depending on whch framework version you are targeting).
Then you can just use the proxy class that VS creates for you.
There's no advantage to writing all of the HTTP code yourself. Actually, there's a big disadvantage, in that you are aren't getting proper data types from the WSDL of your SOAP service.

BingAds API Soap Request

I have been trying to use the BingAds Soap API call to get a keyword performance. But the following request falled for some reason. I would appreciate if someone can tell me where tyhe problem is.It returns the Internal 500 error.
private void button1_Click(object sender, EventArgs e)
{
string xml = #"<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope
xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:v8='https://adcenter.microsoft.com/v8'
xmlns:arr='https://schemas.microsoft.com/2003/10/Serialization/Arrays'>
<soapenv:Header>
<v8:UserName>xxx</v8:UserName>
<v8:Password>xxx</v8:Password>
<v8:DeveloperToken>xxx</v8:DeveloperToken>
<v8:CustomerId>xxx</v8:CustomerId>
<v8:CustomerAccountId>xxx</v8:CustomerAccountId>
<v8:ApplicationToken></v8:ApplicationToken>
</soapenv:Header>
<soapenv:Body>
<v8:SubmitGenerateReportRequest>
<v8:ReportRequesti:type=""v8:KeywordPerformanceReportRequest""xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
<v8:Format>Csv</v8:Format>
<v8:Language>English</v8:Language>
<v8:ReportName>MyReport</v8:ReportName>
<v8:ReturnOnlyCompleteData>false</v8:ReturnOnlyCompleteData>
<v8:Aggregation>Daily</v8:Aggregation>
<v8:Columns>
<v8:KeywordPerformanceReportColumn>AccountId</v8:KeywordPerformanceReportColumn>
<v8:KeywordPerformanceReportColumn>AccountName</v8:KeywordPerformanceReportColumn>
<v8:KeywordPerformanceReportColumn>Keyword</v8:KeywordPerformanceReportColumn>
<v8:KeywordPerformanceReportColumn>KeywordId</v8:KeywordPerformanceReportColumn>
<v8:KeywordPerformanceReportColumn>AdGroupName</v8:KeywordPerformanceReportColumn>
<v8:KeywordPerformanceReportColumn>CostPerConversion</v8:KeywordPerformanceReportColumn>
</v8:Columns>
<v8:Scope>
<v8:AccountIds>
<arr:long>xxx</arr:long>
</v8:AccountIds>
</v8:Scope>
<v8:Time>
<v8:PredefinedTime>LastSevenDays</v8:PredefinedTime>
</v8:Time>
</v8:ReportRequest>
</v8:SubmitGenerateReportRequest>
</soapenv:Body>
</soapenv:Envelope>";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://adcenterapi.microsoft.com/Api/Advertiser/v8/Reporting/ReportingService.svc");
req.ContentType = "text/xml; charset=utf-8";
req.Method = "POST";
req.Accept = "text/xml";
using (StreamWriter writer = new StreamWriter(req.GetRequestStream()))
{
writer.Write(xml);
}
WebResponse response1 = req.GetResponse();
Stream responseStream = response1.GetResponseStream();
StreamReader myStreamReader = new StreamReader(responseStream);
string responseData = myStreamReader.ReadToEnd();
}
AFAIK the Arrays namespace should not be https.
xmlns:arr='http://schemas.microsoft.com/2003/10/Serialization/Arrays'
Also you shouldn't need extra quotes around KeywordPerformanceReportRequest.
"v8:KeywordPerformanceReportRequest"
That should not impact the request, but is not necessary.
I hope this helps!
Eric Urban [MSFT Bing Ads UA]
This line:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://adcenterapi.microsoft.com/Api/Advertiser/v8/Reporting/ReportingService.svc");
Shouldn't you have ?wsdl in the URL, like this:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://adcenterapi.microsoft.com/Api/Advertiser/v8/Reporting/ReportingService.svc?wsdl");

Categories

Resources