Reputation: 251
I have one affiliate account and I need to make a soap
call to get data. I got ready code from one site and I tried to apply it, but I'm getting 500(internal server error)
. My code is given below.
public void getdata()
{
var _url = "http://secure.directtrack.com/api/soap_affiliate.php";
var _action = "http://secure.directtrack.com/api/soap_affiliate.php/dailyStatsInfo";
XmlDocument soapEnvelopeXml = CreateSoapEnvelope();
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
}
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
private static XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelop = new XmlDocument();
soapEnvelop.LoadXml(@"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/1999/XMLSchema""><SOAP-ENV:Body xmlns=""http://soapinterop.org//"" SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""> <q1:Execute xmlns:q1=""http://secure.directtrack.com/api/soap_affiliate.php/dailyStatsInfo""><client xsi:type=""xsd:string"">MyClientNAme</client><add_code xsi:type=""xsd:string"">MyCode</add_code><password xsi:type=""xsd:string"">MyPassword</password><program_id xsi:type=""xsd:int"">161</program_id></q1:Execute></SOAP-ENV:Body></SOAP-ENV:Envelope>");
return soapEnvelop;
}
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
What is the problem? Thanks in advance.
Upvotes: 7
Views: 55719
Reputation: 56
if you are not able to solve you issue through above solution then please extract web exception and try to find the issue, after doing this , i have solved my issue .
catch (WebException ex)
{
if (ex.Response != null)
{
using (var errorResponse = (HttpWebResponse)ex.Response)
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string errorContent = reader.ReadToEnd();
Console.WriteLine($"Error Response Content: {errorContent}");
}
}
Console.WriteLine($"Error: {ex.Message}");
}
Upvotes: 0
Reputation: 151
I went through this as well, I can even tell where you got this code :)
so check it out
webRequest.Headers.Add("SOAPAction", action);
is the issue
simply use
webRequest.Headers.Add("SOAP:Action");
Upvotes: 4
Reputation: 25820
An internal server error means that the error is on the server side. Your code may be calling the service exactly correctly, or you may be passing a parameter that the server doesn't know how to process (but the server code isn't smart enough to tell you so).
Without knowing more about the server and what it expects, it isn't possible to diagnose the issue.
That said, it's possible that your soap envelope is the issue. Are you sure you've entered the correct client name, add code, password, program id, etc?
Upvotes: 6
Reputation: 1
You should try using reflection in order to send data to a web service. Try using something like this:
Uri mexAddress = new Uri(URL);
// For MEX endpoints use a MEX address and a
// mexMode of .MetadataExchange
MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
var binding = new WSHttpBinding(SecurityMode.None);
binding.MaxReceivedMessageSize = Int32.MaxValue;
XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas();
readerQuotas.MaxNameTableCharCount = Int32.MaxValue;
binding.ReaderQuotas = readerQuotas;
//SS Get Service Type and set this type to either Galba and Powersale
string contractName = "";
string operationName = "RegisterMerchant";
object[] operationParameters;// = new object[] { 1, 2 };
// Get the metadata file from the service.
//MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
MetadataExchangeClient mexClient = new MetadataExchangeClient(binding);
mexClient.ResolveMetadataReferences = true;
MetadataSet metaSet = mexClient.GetMetadata(mexAddress, mexMode);
// Import all contracts and endpoints
WsdlImporter importer = new WsdlImporter(metaSet);
Collection<ContractDescription> contracts = importer.ImportAllContracts();
ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();
// Generate type information for each contract
ServiceContractGenerator generator = new ServiceContractGenerator();
var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
foreach (ContractDescription contract in contracts)
{
generator.GenerateServiceContractType(contract);
// Keep a list of each contract's endpoints
endpointsForContracts[contract.Name] = allEndpoints.Where(se => se.Contract.Name == contract.Name).ToList();
}
if (generator.Errors.Count != 0) { throw new Exception("There were errors during code compilation."); }
// Generate a code file for the contracts
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
// Compile the code file to an in-memory assembly
// Don't forget to add all WCF-related assemblies as references
CompilerParameters compilerParameters = new CompilerParameters(
new string[] { "System.dll", "System.ServiceModel.dll", "System.Runtime.Serialization.dll" });
compilerParameters.GenerateInMemory = true;
CompilerResults results = codeDomProvider.CompileAssemblyFromDom(compilerParameters, generator.TargetCompileUnit);
if (results.Errors.Count > 0)
{
throw new Exception("There were errors during generated code compilation");
}
else
{
// Find the proxy type that was generated for the specified contract
// (identified by a class that implements
// the contract and ICommunicationbject)
Type[] types = results.CompiledAssembly.GetTypes();
Type clientProxyType = types
.First(t => t.IsClass && t.GetInterface(contractName) != null && t.GetInterface(typeof(ICommunicationObject).Name) != null);
// Get the first service endpoint for the contract
ServiceEndpoint se = endpointsForContracts[contractName].First();
// Create an instance of the proxy
// Pass the endpoint's binding and address as parameters
// to the ctor
object instance = results.CompiledAssembly.CreateInstance(
clientProxyType.Name,
false,
System.Reflection.BindingFlags.CreateInstance,
null,
new object[] { se.Binding, se.Address },
CultureInfo.CurrentCulture, null);
Type parameterType = types.First(t => t.IsClass && t.Name=="Method()");
Object o = Activator.CreateInstance(parameterType);
FieldInfo[] props = parameterType.GetFields();
FieldInfo fi = parameterType.GetField("NewMerchantDetail");
//PropertyInfo pi = parameterType.GetProperty("NewMerchantDetail");
Type p1Type = fi.FieldType;
//Pass in the values here!!!
Object o1 = Activator.CreateInstance(p1Type);
PropertyInfo pi1 = p1Type.GetProperty("MerchantID");//7
pi1.SetValue(o1, vendingClient.VendingClientID, null);
pi1 = p1Type.GetProperty("FirstName");// John
pi1.SetValue(o1, vendingClient.DescriptiveName, null);
fi.SetValue(o, o1, BindingFlags.Default, null, null);
operationParameters = new object[] { o1 };
// Get the operation's method, invoke it, and get the return value
object retVal = instance.GetType().GetMethod(operationName).
Invoke(instance, operationParameters);
I used this code for distributing data instead of having to insert into each individual database.
Hope it helps!
Upvotes: -2
Reputation: 578
You should really try wrapping your code in one or more try-catch blocks, as the Internal Server Error is likely the result of an unhandled exception.
If the soap xml is malformed, this line would throw an XmlException:
soapEnvelop.LoadXml(@"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/1999/XMLSchema""><SOAP-ENV:Body xmlns=""http://soapinterop.org//"" SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""> <q1:Execute xmlns:q1=""http://secure.directtrack.com/api/soap_affiliate.php/dailyStatsInfo""><client xsi:type=""xsd:string"">MyClientNAme</client><add_code xsi:type=""xsd:string"">MyCode</add_code><password xsi:type=""xsd:string"">MyPassword</password><program_id xsi:type=""xsd:int"">161</program_id></q1:Execute></SOAP-ENV:Body></SOAP-ENV:Envelope>");
This one could produce IOExceptions:
soapEnvelopeXml.Save(stream);
There are probably more, but this should give you a poke in the right direction...
Upvotes: -2