Search code examples
azurewindows-phone-7.1servicebus

Azure Servicebus relay on Windows Phone


I have a client/server application through windows azure relaying. This works well using a console application for both server and client.

Now I want to use Windows Phone as a client, but for some reason, I cannot call the servicebus. I can't add a web reference and when targeting the url in a browser I get the following message:

<s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode><faultstring xml:lang="nl-NL">The message with Action 'GET' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</faultstring></s:Fault>

I have entered the following code in the server app.config:

// sb:// binding
            Uri sbUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "blabla");
            var sbBinding = new NetTcpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.None);
            serviceHost.AddServiceEndpoint(typeof(IMyContract), sbBinding, sbUri);

            // https:// binding (for Windows Phone etc.)
            Uri httpsUri = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespace, "https/" + "blabla");
            var httpsBinding = new BasicHttpRelayBinding(EndToEndBasicHttpSecurityMode.Transport, RelayClientAuthenticationType.None);
            serviceHost.AddServiceEndpoint(typeof(IMyContract), httpsBinding, httpsUri);

And before opening the host, i'm setting the endpoints to discovery mode public.

What else can or do I need to do to make this work with windows phone?


Solution

  • I think you're fairly close. By what I gather you can't add the web reference to your phone project. While that's possible through that path, I wouldn't recommend to make the effort to expose the metadata endpoint through the Relay since you will not use it at runtime. Instead, reference the contract into your Windows Phone project and make a ChannelFactory with BasicHttpBinding and the target address for the BasicHttpRelatBinding endpoint on the service side.

    You've got everything else set up right by what I can tell, including having ACS turned off on the listener so that you can use the regular BasicHttpBinding on the phone.

    EDIT:

    Since that probably wasn't completely clear, here's a service:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    class Program : IEcho
    {
        static void Main(string[] args)
        {
            var sh = new ServiceHost(new Program(), 
                        new Uri("http://clemensv.servicebus.windows.net/echo"));
            sh.Description.Behaviors.Add(
                 new ServiceMetadataBehavior { 
                       HttpGetEnabled = true, 
                       HttpGetUrl = new Uri("http://localhost:8088/echowsdl")});
            var se = sh.AddServiceEndpoint(typeof(IEcho), 
                 new BasicHttpRelayBinding(EndToEndBasicHttpSecurityMode.None, 
                                           RelayClientAuthenticationType.None), String.Empty);
            var endpointBehavior = new TransportClientEndpointBehavior(
                   TokenProvider.CreateSharedSecretTokenProvider("owner", "...key ..."));
            se.Behaviors.Add(endpointBehavior);
            sh.Open();
            Console.WriteLine("Service is up");
            Console.ReadLine();
            sh.Close();
        }
    
        public string Echo(string msg)
        {
            return msg;
        }
    }
    

    The contract IEcho is trivial and not shown. What you'll notice is that I have a ServiceMetadataBehavior hanging "off on the side" exposed through localhost that will give you WSDL if you hit that URI. You can use that address with the "Add Web Reference" client in Visual Studio to create the proxy on Windows Phone; that proxy will use BasicHttpBinding on the phone. I just did that and it works as expected in a trivial phone app (with the reference renamed to MySvc)

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            var client = new MySvc.EchoClient();
            client.EchoCompleted += OnClientOnEchoCompleted;
            client.EchoAsync("foo");
        }
    
        void OnClientOnEchoCompleted(object sender, EchoCompletedEventArgs c)
        {
            this.textBox1.Text = c.Result;
        }