4

I am writing a C# client that calls a web service to authenticate clients. I used add service reference to add the wsdl file to my project and the proxy class generated successfully.

I am creating new instances of objects that will be used like this:

authenticateAccessPortTypeClient client = new authenticateAccessPortTypeClient();
authDetails details = new authDetails();
returnResult result = new returnResult();

This is my code when the user needs to be authenticated:

// This is details that needs to be passed in the header of the SOAP Envelope
details.key = "some key as string";
details.mode = "the mode as string";

// This is a parameter that is passed in the body of the SOAP Envelope
string memKey = "the member key as string";

result = client.authenticateAccess(details, memKey);

textBoxResult.Text = result.message;

My soap response looks like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:example="www.example.com">
   <soapenv:Header/>
   <soapenv:Body>
      <example:authenticateAccessResponse>
         <result>
            <message>some string</message>
         </result>
      </example:authenticateAccessResponse>
   </soapenv:Body>
</soapenv:Envelope>

And returnResults looks like this in the generated proxy class:

public partial class returnResult : object, System.ComponentModel.INotifyPropertyChanged {

    private string messageField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
    public string message {
        get {
            return this.messageField;
        }
        set {
            this.messageField = value;
            this.RaisePropertyChanged("message");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

I keep on getting the error: Object reference not set to an instance of an object and returnResult is null.

J2D8T
  • 827
  • 11
  • 24
  • 2
    On what line do you get that error? – Roy Dictus Nov 21 '13 at 13:45
  • The last line where I am trying to display the result.message. – J2D8T Nov 21 '13 at 13:47
  • Almost all cases of `NullReferenceException` are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. Obviously, if `returnResult` is null, then `returnResult.message` will throw `NullReferenceException`. – John Saunders Nov 21 '13 at 13:48
  • 1
    All that code and no concept of a NRE nor how to debug them. Hmmm. –  Nov 21 '13 at 13:50
  • So either `textBoxResult` or `result` is `null`. But the SOAP result you show is not empty and the `message` property is filled in... I would try `var result = client.authenticateAccess(details, memKey);` instead of your declaration and call above, and with the debugger make sure that indeed `result` is null. And btw how did you get that SOAP result, using a sniffer? – Roy Dictus Nov 21 '13 at 13:52
  • @John Saunders I understand the reasons for getting the NRE but as I see it I am creating a new instance by: returnResult result = new returnResult(); and then assigning the method call to result so I don't understand where it is going wrong. I will go read through the post you provided to see if I can understand better. – J2D8T Nov 21 '13 at 14:01
  • Try this: `int i=1; i=2;` what's the value of `i`? – John Saunders Nov 21 '13 at 14:03
  • @Roy Dictus the error is on result.message. I wrote a separate class that catches the soap request and response and displays them as string using MessageInspector(), IClientMessageInspector and IEndpointBehaviour. – J2D8T Nov 21 '13 at 14:06
  • @John Saunders I know for you experienced guys this is a simple error but I am just trying to understand where I am going wrong. So by your example I am overwriting returnResult? – J2D8T Nov 21 '13 at 14:09
  • yes, in the example, you are overwriting `returnResult`. So if the service call returns `null`, then `returnResult` will be `null`. Hence the NRE. Next question: why does the service return `null`? – John Saunders Nov 21 '13 at 14:13
  • @J2D8T: Yes, you are overwriting returnResult, because you initialize it when you declare it and then you overwrite that value with the result of the actual call. But of course the real issue is that the returned result is null -- – Roy Dictus Nov 21 '13 at 14:13
  • @RoyDictus if I use var result = client.authenticateAccess(details, memKey); it shows that result is null. I also removed the resturnResult constructor from the top. – J2D8T Nov 21 '13 at 14:15
  • Most likely, your proxy classes have `authenticateAccessResponse` in the wrong namespace. What kind of service is this? Can you post bits of the WSDL? Especially the `message` that describes the result, and the `binding` elements that use those messages. – John Saunders Nov 21 '13 at 14:16
  • @JohnSaunders but the service call never returns null it returns the value I am looking for each time I run the code. That's why I don't understand it. – J2D8T Nov 21 '13 at 14:18
  • @J2D8T: if the proxy class is expecting the result to be in one namespace, but it in fact is in another, then then expected result is not present, and the actual result is `null`. – John Saunders Nov 21 '13 at 14:21
  • The wsdl is referencing php functions. – J2D8T Nov 21 '13 at 14:22
  • @J2D8T: Are you absolutely sure the generated WSDL is correct? Because the proxy classes are created based on the WSDL; so, like John Saunders says, it might be a namespace mismatch and the proxy class gets data back that it doesn't know how to handle. – Roy Dictus Nov 21 '13 at 14:27
  • Yes, just as I thought: an RPC-style web service. Those are always trouble. Note the `type=` on the message parts. That doesn't conform to WS-I BP1.1 because it's ambiguous - it says what the _contents_ should look like, but not what namespace the _part_ should be in! – John Saunders Nov 21 '13 at 14:27
  • @JohnSaunders: True about the ambiguity but to me the WSDL looks OK. – Roy Dictus Nov 21 '13 at 14:30
  • I have updated the title and the tags. Refresh the page, then look at the "Related" section on the right side of the page. You'll find several other questions on the same topic. – John Saunders Nov 21 '13 at 14:32
  • @JohnSaunders the problem is I can't change the wsdl to much because there are other clients using it on php client applications. I created this test one to see if i can figure out how to solve my problem. – J2D8T Nov 21 '13 at 14:33
  • Seems like if you receive the response that your deserializer does not deserialize the response properly to your objects. You might need to add override to create the namespace prefixes. I had similar issue when integrating to java service from .NET. – Janne Matikainen Nov 21 '13 at 14:47
  • If it is any help I know that the php function returns an associative array. – J2D8T Nov 21 '13 at 14:51

1 Answers1

2

After much Googling and debugging and thanks to the users who commented on this post I solved my problem.

The actual problem wasn't on the client side but rather on the WSDL file itself. I changed the binding style of the WSDL file to use document with literal wrapped. The type structure of my wsdl file was changed to the following:

<xsd:element name="nameOfType">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="1" maxOccurs="1" name="element1" type="xsd:string"/>
        <xsd:element minOccurs="1" maxOccurs="1" name="element2" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

The complexType tag needs to be wrapped within another element tag to use literal wrapped an the name attribute is set in the first element.

The message tags then changed to:

<wsdl:message name="messageName">
    <wsdl:part name="nameOfType" element="tns:nameOfType"/>
</wsdl:message>

*Notice the element attribute instead of the type attribute

And the binding looks like this:

<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="nameOfWebMethod">
  <soap:operation soapAction="nameOfWebMethod"/>
  <wsdl:input>
    <soap:body use="literal"
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:youNamespace:nameOfService"/>
    <soap:header message="tns:messageName" part="nameOfType" use="literal"/>
  </wsdl:input>
  <wsdl:output>
    <soap:body use="literal"
               encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
               namespace="urn:youNamespace:nameOfService"/>
  </wsdl:output>
</wsdl:operation>

Thanks to @John Saunders & @Roy Dictus for your input and guidance.

J2D8T
  • 827
  • 11
  • 24