views:

57

answers:

3

I've created a web service , which can a method to set the user credential using Microsoft.Web.Services3.WebServicesClientProtocol. The sample code is :

<WebMethod()> _
    Public Sub ClientCredential1(Of TSecurityToken As SecurityToken)_
         (ByVal UserCred As Microsoft.Web.Services3.Security.Tokens.UsernameToken)

        Dim cProxy As New Microsoft.Web.Services3.WebServicesClientProtocol()
        cProxy.SetClientCredential(UserCred)
    End Sub

When I run the web service it gives this error:

"Microsoft.Web.Services3.Security.Tokens.UsernameToken cannot be serialized because it does not have a parameterless constructor."

Does any one know where is the problem ?

+2  A: 

The root of the problem here is that the class Microsoft.Web.Services3.Security.Tokens.UsernameToken doesn't have a parameter-less constructor. It's got 3 of them, but they all demand a parameter. UsernameToken constructors on MSDN.

  • UsernameToken (XmlElement)
  • UsernameToken (String, String)
  • UsernameToken (String, String, PasswordOption)

The problem is that during deserialization, XmlSerializer calls the parameterless constructor to create an instance of that class. It can't deserialize a type that doesn't have a parameterless constructor.

I get the sense there's not much you can do to work around this problem. I'd only suggest creating a partial class, and implementing that zero-param constructor yourself.

'ensure namespacing is correct.
Public Partial Class UsernameToken
    Public Sub New()
    End Sub    
End Class
p.campbell
Since UsernameToken is defined in a referenced assembly, I don't think you can add a constructor using a partial class definition... I think that only works when you have the source code for all parts of the class.
Richard Beier
@Richard: I figured as much. It was a long shot.
p.campbell
A: 

p. campbell is right, it's because the XmlSerializer requires a parameterless constructor.

I don't know WSE, but from looking at this post on Aleem's Weblog, I don't think the UsernameToken is supposed to be passed as a regular argument to a web method - it's supposed to be passed in the WS-Security SOAP headers. You get the proxy to pass it in the headers by calling SetClientCredential(). Here's the example from the above blog post:

Dim oService As New WSETestService.ServiceWse

Dim U As New UsernameToken(“<User_Name>”, “<Password>”, PasswordOption.SendHashed)
oService.SetClientCredential(U)
Richard Beier
A: 

You can't use a parameter of the type Microsoft.Web.Services3.Security.Tokens.UsernameToken in a web service, as it's not possible to serialise (or more specifically not possible to deserialise).

Create a class that just contains the data that you need to create a UsernameToken and use as parameter type. The client side would not create a real UsernameToken object anyway, there is a proxy class created from the WSDL information.

Guffa