SOAP Headers not working - Working example needed

I have a C# Webservice, asmx, with authentication header, and a Delphi consumer.
It fails and the error says: Object reference not set to an instance of an object. It is the from the line where the web service tries to use the cridential I am trying to pass.
I have searched the internet, and a lot of people have problems with soap headers, I found out.
I now tried it on Delphi 2010, and at least the WSDL file, becomes very different that the file from a Delphi 2006. BUT the result is exact the same.

Does any one have a working example of a Delphi asmx web service consumer, that uses SOAP headers?
adwizaAsked:
Who is Participating?
 
ebob42Commented:
You need to send the SOAP Header for every request. I see the call to

(q as ISOAPHeaders).Send(cr);

Just before you cal the q.GetQuery(qreq);
which should work

But in the last two lines, you use the HTTPRIO and call (HTTPRIO as QuerySoap).GetQuery(qreq); which will not work because you didn't pass the SOAP header to that one.

If it's the q.GetQuery that fails, then it looks like the C# code that's having a problem with your client could be:

using  (SoSession = new soAuthentication(SoCredentials.Username, SoCredentials.Secret))

Can you modify the C# server? Try to pass the literal strings here, just to see if you can make a connection.

The SoCredetials.Secret field feels fragile. Is that base64 encoded?
0
 
ebob42Commented:
I have written several clients (and servers) using SOAP Headers. There are examples in my courseware manual on Delphi 2010, but also some articles on the web (but not using Delphi 2010 as far as I remember).

What is the WSDL URL? What is the SOAP request that you send to the server? Is the SOAP header present?

Do you have an example SOAP request from a client that works (so we can compare what you send and what the working client sends, just in case you need to tweak your request a little bit).

SOAP Headers for .NET servers should work with little or no problems, so it must be something special why it fails in your case...
0
 
adwizaAuthor Commented:
If it is possible in Delphi 2006, this would ease thing a bit.

I have uploaded the files here: adwiza.com/x/EDS.WebService.zip and adwiza.com/x/SOAP_test.zip
You might have a problem with compiling the web service as it uses a DLL from a CRM system called SuperOffice.
It is a work in progress so no request has worked yet, except from a test C# program.
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
ebob42Commented:
I'm sorry, but I'm not going to download and test your programs. Could you just show the lines of code that create and send the SOAP header with the request?

Then, intercept the SOAP request and compare it to what the C# client is sending.
0
 
adwizaAuthor Commented:
Thats OK, I understand. But the service is not available from outside, that was why I just sent you the files.

procedure TfrmSOAP_test.Button1Click(Sender: TObject);
var
      q:            QuerySoap;
      cr:     EdsHeader;
      qreq:      QueryRequest;
      qres:      QueryResponse;
begin
      //(HTTPRIO as QuerySoap).GetQuery('select top 10 contact_id,name from crm5.contact');

      q:=GetQuerySoap(false,'',HTTPRIO);

      cr:=EdsHeader.Create;
      cr.Authentication:='CRM5';
      cr.Username:='ba';
      cr.Secret:='5ueCYiqjAUa7m9HOOuav9A==';

      (q as ISOAPHeaders).Send(cr);

      //HTTPRIO.SOAPHeaders.Send(cr);

      qreq:=QueryRequest.Create;
      qreq.DataSource:='adwiza';
      qreq.Query:='select contact_id,name from crm5.contact';

      qres:=QueryResponse.Create;

      qres.Response:=Response.Create;

      qres:= q.GetQuery(qreq);

      ShowMessage(qres.Error);
      ShowMessage(qres.Response.schema.ToString);


      HTTPRIO.URL:='http://bruno-pc/edsservice/query.asmx';
      (HTTPRIO as QuerySoap).GetQuery(qreq);

end;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

using System.Data.Odbc;
using SuperOffice;
using System.Web.Services.Protocols;
using System.Xml;
using System.Data;

namespace EDS.WebService
{
    /// <summary>
    /// EDS Webservice
    /// </summary>
    [WebService(Namespace = "http://adwiza.com/edswebservice")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    // [System.Web.Script.Services.ScriptService]
    public class Query //: System.Web.Services.WebService
    {
        public const string SO_SESSION = " _SESSION";
        public const string SO_SESSION_ID = " _SESSION_ID";

        private soAuthentication _SoAuthentication = null;
        public EdsHeader SoCredentials;

        [WebMethod]
        [SoapHeader("SoCredentials", Direction = SoapHeaderDirection.In)]
        public List<QueryResponse> GetQueries(List<QueryRequest> queries)
        {
            List<QueryResponse> response = new List<QueryResponse>();
            try
            {
                // Authenticate
                using (SoSession = new soAuthentication(SoCredentials.Username, SoCredentials.Secret))
                {
                    foreach (QueryRequest qr in queries)
                    {
                        try
                        {
                            QueryResponse r = PerformQuery(qr);
                            if (r != null)
                                response.Add(r);
                        }
                        catch (Exception ex)
                        {
                            response.Add(new QueryResponse { Error = ex.Message, StackError = ex.StackTrace });
                        }
                    }

                    // LogOut Authentication
                    //Logout();
                }
            }
            catch (Exception ex)
            {
                // Get the inner most exception
                if (ex.InnerException != null)
                    while (ex.InnerException != null)
                        ex = ex.InnerException;

                response.Add(new QueryResponse { Error = ex.Message });
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SoCredentials", Direction = SoapHeaderDirection.In)]
        public QueryResponse GetQuery(QueryRequest query)
        {
            QueryResponse response = null;
            try
            {
                // Authenticate
                using  (SoSession = new soAuthentication(SoCredentials.Username, SoCredentials.Secret))
                {
                    try
                    {
                        QueryResponse r = PerformQuery(query);
                        if (r != null)
                            response = r;
                    }
                    catch (Exception ex)
                    {
                        response = new QueryResponse { Error = ex.Message, StackError = ex.StackTrace };
                    }

                    // LogOut Authentication
                    //Logout();
                }
            }
            catch (Exception ex)
            {
                // Get the inner most exception
                if (ex.InnerException != null)
                    while (ex.InnerException != null)
                        ex = ex.InnerException;

                response = new QueryResponse { Error = ex.Message, StackError = ex.StackTrace };
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SoCredentials", Direction = SoapHeaderDirection.In)]
        public object GetMetadata(string type)
        {
            return new object { };
        }

        /*****************************************************************************************************/

        private QueryResponse PerformQuery(QueryRequest request)
        {
            QueryResponse response = null;

            // Get Connection from EDS Script
            request.DataSource = "adwiza";
            string connectionString = String.Format("dsn={0}; uid={1}; pwd={2};", request.DataSource, "KITCHEN", "KITCHEN");

            // Perform the requested query
            using (OdbcConnection con = new OdbcConnection(connectionString))
            {
                using (OdbcCommand cmd = new OdbcCommand())
                {
                    cmd.Connection = con;
                    cmd.CommandType = System.Data.CommandType.Text;
                    cmd.CommandText = request.Query;

                    con.Open();

                    OdbcDataAdapter adapter = new OdbcDataAdapter(cmd);
                    DataSet ds = new DataSet();
                    adapter.Fill(ds);

                    response = new QueryResponse { Response = ds };

                    con.Close();
                }
            }
            return response;
        }

        /*****************************************************************************************************/

        public void Logout()
        {
            try
            {
                if (SoSession != null)
                    SoSession.Dispose();
            }
            catch (Exception ex)
            {
                // Get the inner most exception
                if (ex.InnerException != null)
                    while (ex.InnerException != null)
                        ex = ex.InnerException;
                throw new Exception(ex.Message, ex);
            }
        }

        protected soAuthentication SoSession
        {
            get { return _SoAuthentication; }
            set { _SoAuthentication = value; }
        }

    }

    public class EdsHeader : SoapHeader
    {
        public string Authentication;
        public string Username;
        public string Secret;
    }
    public class QueryRequest
    {
        public QueryRequest() { }

        public string DataSource { get; set; }
        public string Query { get; set; }
    }
    public class QueryResponse
    {
        public QueryResponse() { this.Error = ""; this.Response = null; }

        public string Error { get; set; }
        public string StackError { get; set; }
        public bool hasError { get { return String.IsNullOrEmpty(this.Error) ? false : true; } }
        public DataSet Response { get; set; }
    }
}
0
 
adwizaAuthor Commented:
Sorry, I only single step to the line showing the error, so the second call is never done.

But I tried this:
q:=GetQuerySoap(true,'',HTTPRIO);
True instead of false and I did get a result back.

Thank you very much for your help, even if I found out a soulution my self, you deserve the points, and it is not becauseI have the book "Delphi XML, SOAP and web services development" from you ;o))
0
 
adwizaAuthor Commented:
To make it run with Delphi 2006.

    public class EdsHeader : SoapHeader
    {
        public string Authentication;
        public string Username;
        public string Secret;
    }


Should be changed to:


    [System.Xml.Serialization.XmlRoot("EdsHeader")]
    [Serializable]
    public class EdsHeader: SoapHeader
    {
        [System.Xml.Serialization.XmlAttribute]
        public String Authentication;
        [System.Xml.Serialization.XmlAttribute]
        public String Username;
        [System.Xml.Serialization.XmlAttribute]
        public String Secret;
    }
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.