我有一个联属帐户,我需要拨打
soap
电话来获取数据。我从一个网站获取了准备好的代码,并尝试应用它,但我得到了 500(internal server error)
。我的代码如下。
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);
}
}
问题是什么?预先感谢。
服务器内部错误意味着错误发生在服务器端。您的代码可能完全正确地调用服务,或者您可能正在传递服务器不知道如何处理的参数(但服务器代码不够聪明,无法告诉您这一点)。
如果不了解有关服务器及其期望的更多信息,就无法诊断问题。
也就是说,问题可能出在你的肥皂信封上。您确定输入了正确的客户名称、添加代码、密码、程序 ID 等吗?
我也经历过这个,我什至可以告诉你这个代码是从哪里得到的:)
所以检查一下
webRequest.Headers.Add("SOAPAction", action);
是问题所在
简单使用
webRequest.Headers.Add("SOAP:Action");
如果您无法通过上述解决方案解决您的问题,请提取网络异常并尝试找到问题,完成此操作后,我已经解决了我的问题。
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}");
}
您确实应该尝试将代码包装在一个或多个 try-catch 块中,因为内部服务器错误可能是未处理异常的结果。
如果soap xml格式错误,此行将抛出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>");
这个可能会产生 IOExceptions:
soapEnvelopeXml.Save(stream);
可能还有更多,但这应该会给你一个正确的方向......
您应该尝试使用反射来将数据发送到 Web 服务。尝试使用这样的东西:
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);
我使用此代码来分发数据,而不必插入到每个单独的数据库中。
希望有帮助!