简体   繁体   English

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

[英]Soap call gives 500 (internal server error) in c#

I have one affiliate account and I need to make a soap call to get data. 我有一个联盟帐户,我需要拨打soap电话来获取数据。 I got ready code from one site and I tried to apply it, but I'm getting 500(internal server error) . 我从一个站点获得了准备好的代码,我尝试应用它,但我得到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. 提前致谢。

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? 您确定输入了正确的客户名称,添加代码,密码,程序ID等吗?

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

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. 您应该尝试将代码包装在一个或多个try-catch块中,因为内部服务器错误可能是未处理异常的结果。

If the soap xml is malformed, this line would throw an XmlException: 如果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>");

This one could produce IOExceptions: 这个可以产生IOExceptions:

soapEnvelopeXml.Save(stream);

There are probably more, but this should give you a poke in the right direction... 可能还有更多,但这应该会给你一个正确的方向戳...

You should try using reflection in order to send data to a web service. 您应该尝试使用反射,以便将数据发送到Web服务。 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! 希望能帮助到你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM