0

[UPDATE] I do not think this is a duplicate, as the post in question is using MyServiceSoapClient() and I am not.

I am writing a SOAP web service call using C# in Visual Studio 2017.

Customizing the example code from the vendor I am able to execute a report and then stream the resulting file to my local file system. So far so good, the file is downloaded in XML format, the default.

If I add a custom HTTP Header to the SOAP envelope I can modify the format of the report. I need to send the following:

<headers>
<US-DELIMITER>|</US-DELIMITER>
</headers>

However, I cannot for the life of me figure out how to do this. I believe I can do it either programmatically or by adding something in the App.config file. I would prefer to change the latter.

My App.Config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
    <system.serviceModel>
        <bindings>      
            <wsHttpBinding>
                <binding name="WSHttpBinding_IBIStreamService" maxReceivedMessageSize="2000000">
                    <security mode="Transport">
                        <transport clientCredentialType="None" />
                    </security>
                </binding>
                <binding name="WSHttpBinding_IBIDataService" maxReceivedMessageSize="2000000">
                    <security mode="Transport">
                        <transport clientCredentialType="None" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
          <endpoint address="https://service4.ultipro.com/services/BIDataService"
              binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBIDataService"
              contract="BIDataService.IBIDataService" name="WSHttpBinding_IBIDataService">           
          </endpoint>
            <endpoint address="https://service4.ultipro.com/services/BIStreamingService"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBIStreamService"
                contract="BIStreamingService.IBIStreamService" name="WSHttpBinding_IBIStreamService" />
        </client>
    </system.serviceModel>
</configuration>

The important part of my code looks like this:

namespace BIWebServiceExample
{
    using System;
    using System.IO;
    using System.ServiceModel;
    using UltiProBusinessReports.BIDataService;
    using UltiProBusinessReports.BIStreamingService;

    class Program
    {
        private static DataContext Context { get; set; }
        private static BIDataServiceClient DataClient { get; set; }
        private static String Path { get; set; }
        private static String Report { get; set; }

        // Entry point of the application
        static void Main(string[] args)
        {
            Path = "XXXXX;
            DataClient = new BIDataServiceClient("WSHttpBinding_IBIDataService");
            Context = DoAuthenticate();

            if (Context.Status == ContextStatus.Ok)
            {
                Report = "'XXXXX']";
                ReportResponse response = ExecuteReport(Context, DataClient, Report);
                if (response.Status == ReportRequestStatus.Success)
                {
                    GetReportStreamFromResponse(response, "XXX.csv");
                }
                else
                {
                    Console.WriteLine(response.StatusMessage);
                }

            }
            else
            {
                // Inspect the StatusMessage on an authentication failure
                Console.WriteLine(Context.StatusMessage);
                Console.ReadKey(true);
            }
        }

        private static void GetReportStreamFromResponse(ReportResponse response, String outFile)
        {
            string msg;
            Stream input = null;
            BIStreamServiceClient streamClient = null;
            try
            {
                streamClient = new BIStreamServiceClient("WSHttpBinding_IBIStreamService", new EndpointAddress(response.ReportRetrievalUri));

                ReportResponseStatus status;
                do
                {
                    status = streamClient.RetrieveReport(response.ReportKey, out msg, out input);
                } while (status == ReportResponseStatus.Working);

                if (status == ReportResponseStatus.Failed)
                {
                    Console.WriteLine("Failed to retrieve report due to \"{0}\"", msg);
                    return;
                }
                using (StreamReader reader = new StreamReader(input))
                {
                    using (Stream output = new FileStream("C:\\temp\\" + outFile, FileMode.Create, FileAccess.Write))

                    {
                        using (StreamWriter writer = new StreamWriter(output))
                        {
                            int bytesRead;
                            char[] buffer = new char[1024];
                            while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                writer.Write(buffer, 0, bytesRead);
                            }
                        }
                    }
                }
            }
            finally
            {
                if (input != null)
                {
                    input.Close();
                }
                CloseClientProxy(streamClient);
            }
        }

        private static void CloseClientProxy(ICommunicationObject client)
        {}

        private static DataContext DoAuthenticate()
        {return ThisContext;}

        private static ReportResponse ExecuteReport(DataContext context, BIDataServiceClient dataClient, String Report)
        {
            ReportResponse response =
                        dataClient.ExecuteReport(
                            new ReportRequest
                            {ReportPath = Path + Report
                            },context);
            return response;
        }
    }
}

Any help would be greatly appreciated.

Bryan Schmiedeler
  • 2,977
  • 6
  • 35
  • 74
  • I assume BIDataServiceClient was generated from a reference on the project? (a proxy based on the service definition somewhere?) – JuanR Jun 01 '17 at 21:39
  • Yes. But the reference doesn't expose this additional header. The guy at the company whose service I am consuming says that the header must be in the SOAP Envelope. – Bryan Schmiedeler Jun 01 '17 at 21:41
  • 1
    Possible duplicate of [How to add HTTP Header to SOAP Client](https://stackoverflow.com/questions/18886660/how-to-add-http-header-to-soap-client) – Clint Jun 01 '17 at 23:11
  • Are you using a WCF service or a legacy one? – JuanR Jun 02 '17 at 13:50
  • Juan, I am very new to the MS Stack, but I believe that I am using WCF. I am using .Net Framework 4.5.2 and using System.ServiceModel. All the examples on the web that I have seen of adding an optional http header seem to use something like the SystemMessageInspector or use a System.WebServices. Everything works properly in this program Except not being able to add this header. – Bryan Schmiedeler Jun 02 '17 at 15:12
  • I see. This may help: https://stackoverflow.com/questions/1976217/how-to-add-custom-soap-headers-in-wcf – JuanR Jun 02 '17 at 15:26
  • That looks very promising. I will give this a try. Thank you, will let you know. – Bryan Schmiedeler Jun 02 '17 at 15:28

0 Answers0