An explicit conversion exists

Hey!

I've tryed to compile the following code:

public class QueryService : QueryContract
{
public void Query(string query)
{

EndpointAddress replyTo = OperationContext.Current.IncomingMessageHeaders.ReplyTo;
System.Xml.UniqueId messageId = OperationContext.Current.IncomingMessageHeaders.MessageId;
CustomBinding binding = new CustomBinding(new TextMessageEncodingBindingElement(), new HttpTransportBindingElement());

using (new OperationContextScope())
{
using (ChannelFactory<QueryContract> factory = new ChannelFactory<QueryContract>(binding, replyTo))
{
QueryCallbackContract callback = factory.CreateDuplexChannel(); //error
callback.Response("bar");
}
}
}
}

but I'm getting this error:
//-------------------------------------------------------------------------------
Error 1 Cannot implicitly convert type 'Test.QueryContract' to 'Test.QueryCallbackContract'. An explicit conversion exists (are you missing a cast )
/-------------------------------------------------------------------------------

How to explicitly convert it
(QueryCallbackContract callback = factory.CreateDuplexChannel();)

Thanks.

[melack]


Answer this question

An explicit conversion exists

  • Timmy Lajaunie

    QueryCallbackContract callback = OperationContext.Current.GetCallbackChannel<QueryCallbackContract>();

    I don't know why but callback is null.
    Can anyone please explain that to me why there is no instance
    Thanks.

    [melack]

  • cosmicstudio

    You will also need to set the CallbackContract property of the ServiceContractAttribute annotation.

    For example:

    [ServiceContract(CallbackContract=typeof(QueryCallbackContract))]
    public interface QueryContract
    {
    [OperationContract(IsOneWay = true)]
    void Query(string query);
    }

    public interface QueryCallbackContract
    {
    [OperationContract(IsOneWay = true)]
    void Response(string response);
    }

    -- Justin

  • originsnone

    Hey!

    Now I have another problem. I get this error:
    Object reference not set to an instance of an object.

    service side:

    using (new OperationContextScope())
    {
    using (ChannelFactory<QueryContract> factory = new ChannelFactory<QueryContract>(binding, replyTo))
    {
    QueryCallbackContract callback = OperationContext.Current.GetCallbackChannel<QueryCallbackContract>();
    OperationContext.Current.OutgoingMessageHeaders.RelatesTo = messageId;


    callback.Response("bar"); //error

    }
    }

    [melack]


  • Big Ticket

    It looks like QueryService is your Service, QueryCallbackContract is the callback contract (an interface), and Query is the interface method that has been annotated with OperationContract.
    If this is true, then getting sending a message back to the sender (client) is as follows:
    public void Query(String query){
    ...
    QueryCallbackContract callback = OperationContext.Current.GetCallbackChannel<QueryCallbackContract>();
    // you can then invoke the callback method
    ...
    }
    -- justin smith


  • volkerm

    Hey!

    This is my code:


    Client:
    ------

    [ServiceContract]
    public interface QueryContract
    {
    [OperationContract(IsOneWay = true)]
    void Query(string query);
    }

    [ServiceContract]
    public interface QueryCallbackContract
    {
    [OperationContract(IsOneWay = true)]
    void Response(string response);
    }


    class QueryCallbackService : QueryCallbackContract
    {
    public void Response(string response)
    {
    UniqueId relatesTo = OperationContext.Current.IncomingMessageHeaders.RelatesTo;
    }
    }


    class Program
    {
    static void Main(string[] args)
    {
    CustomBinding binding = new CustomBinding(new TextMessageEncodingBindingElement(), new HttpTransportBindingElement());
    ChannelFactory<QueryContract> factory = new ChannelFactory<QueryContract>(binding, new EndpointAddress("http://localhost:8001/destination/"));
    QueryContract channel = factory.CreateChannel();

    using (new OperationContextScope())
    {
    OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://localhost:8002/callback/");
    OperationContext.Current.OutgoingMessageHeaders.MessageId = new UniqueId();

    channel.Query("foo");

    }
    }
    }


    Service:
    --------

    [ServiceContract]
    public interface QueryContract
    {
    [OperationContract(IsOneWay = true)]
    void Query(string query);
    }

    [ServiceContract]
    public interface QueryCallbackContract
    {
    [OperationContract(IsOneWay = true)]
    void Response(string response);
    }


    class QueryService : QueryContract
    {

    public void Query(string query)
    {

    EndpointAddress replyTo = OperationContext.Current.IncomingMessageHeaders.ReplyTo;
    UniqueId messageId = OperationContext.Current.IncomingMessageHeaders.MessageId;
    CustomBinding binding = new CustomBinding(new TextMessageEncodingBindingElement(), new HttpTransportBindingElement());

    ChannelFactory<QueryContract> factory = new ChannelFactory<QueryContract>(binding, replyTo);

    using (new OperationContextScope())
    {
    QueryCallbackContract channel = OperationContext.Current.GetCallbackChannel<QueryCallbackContract>();
    OperationContext.Current.OutgoingMessageHeaders.RelatesTo = messageId;

    channel.Response("bar"); //ERROR: Object reference not set to an instance of an object
    }
    }

    }

    class Program
    {
    static void Main(string[] args)
    {
    using (ServiceHost serviceHost = new ServiceHost(typeof(QueryService)))
    {
    CustomBinding binding = new CustomBinding(new TextMessageEncodingBindingElement(), new HttpTransportBindingElement());
    serviceHost.AddServiceEndpoint(typeof(QueryContract), binding, "http://localhost:8001/destination/");
    serviceHost.Open();
    Console.WriteLine("Service Running - Press Any key to quit");
    Console.ReadLine();
    serviceHost.Close();
    }
    }
    }


    Thanks in advance.

    [melack]

  • MrFaith

    It works now.
    If I look at the svctraceviewer tool I can see the [SOAP Message Header]:

    s:mustUnderstand 1
    a:Action http://tempuri.org/QueryContract/Query
    a:Address http://localhost:8004/reply
    a:MessageID urn:uuid:42a6a06e-77a1-4369-8162-d60b1783e7df
    s:mustUnderstand 1
    a:To net.tcp://localhost:8005/duplex

    and

    s:mustUnderstand 1
    a:Action http://tempuri.org/QueryContract/Response
    a:RelatesTo urn:uuid:42a6a06e-77a1-4369-8162-d60b1783e7df
    s:mustUnderstand 1
    a:To http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous

    Thanks.

    [melack]

  • _cham

    Thanks, Justin.
    That's it.

    [melack]

  • la

    What does the client look like Does it provide an instance of the callback contract before invoking the service

    For example, here "IServiceDuplexCallback" is the callback interface provided in metadata to the client when svcutil.exe generated the proxy. You have to create an instance of a class that implements that interface, then when you instantiate the proxy, provide it in the InstanceContext:

    CALLBACK INTERFACE IMPLEMENTATION

    class ServiceCallback : IServiceDuplexCallback

    {... class implementation }

    CODE TO INVOKE PROXY

    InstanceContext context = new InstanceContext(new ServiceCallback());

    ServiceDuplexProxy proxy = new ServiceDuplexProxy(context);



  • An explicit conversion exists