Soap 调用在 c# 中给出 500(内部服务器错误)

问题描述 投票:0回答:5

我有一个联属帐户,我需要拨打

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

问题是什么?预先感谢。

c# soap
5个回答
6
投票

服务器内部错误意味着错误发生在服务器端。您的代码可能完全正确地调用服务,或者您可能正在传递服务器不知道如何处理的参数(但服务器代码不够聪明,无法告诉您这一点)。

如果不了解有关服务器及其期望的更多信息,就无法诊断问题。

也就是说,问题可能出在你的肥皂信封上。您确定输入了正确的客户名称、添加代码、密码、程序 ID 等吗?


4
投票

我也经历过这个,我什至可以告诉你这个代码是从哪里得到的:)

所以检查一下

webRequest.Headers.Add("SOAPAction", action);

是问题所在

简单使用

webRequest.Headers.Add("SOAP:Action");

0
投票

如果您无法通过上述解决方案解决您的问题,请提取网络异常并尝试找到问题,完成此操作后,我已经解决了我的问题。

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

-2
投票

您确实应该尝试将代码包装在一个或多个 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);

可能还有更多,但这应该会给你一个正确的方向......


-2
投票

您应该尝试使用反射来将数据发送到 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);

我使用此代码来分发数据,而不必插入到每个单独的数据库中。

希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.