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

时间:2013-04-19 12:33:57

标签: c# soap

我有一个联盟帐户,我需要进行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);
    }
}

有什么问题?提前谢谢。

4 个答案:

答案 0 :(得分:5)

内部服务器错误表示错误发生在服务器端。您的代码可能正确地正在调用服务,或者您可能正在传递服务器不知道如何处理的参数(但服务器代码不够智能,无法告诉您)。

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

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

答案 1 :(得分:5)

我也经历了这个,我甚至可以告诉你这里有什么代码:)

所以检查一下

  $('.open-modal')
            .each(function() {
                var $this = $(this);

                $this.on("click",
                    function() {
                        $("#Debate").val($(this).data('debate'));
                        $("#Team").val($(this).data('team'));
                        $("#modalTitle").val($(this).data('titulo'));

                        $('#myModal').modal('show');
                    });

            });

是问题

只需使用

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

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

希望它有所帮助!