Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

Silverlight 2 and WCF - Protocol Error RSS

11 replies

Last post Apr 10, 2009 08:45 AM by harsha_hs

(0)
  • guylemar

    guylemar

    Member

    16 Points

    4 Posts

    Silverlight 2 and WCF - Protocol Error

    May 29, 2008 06:33 AM | LINK

    Hi there, 

    I have a WCF service (VS2008) project that seems to work ok. I have a console application that can connect to the WCF service (where VS hosts the WCF service so it can be debugged); and that console app can make calls to the service ok. (All of these projects are in the same solution and execute on the local host.)

    I have modified the endpoint in the app.config file of the WCF library to use basicHttpBinding (instead of wsHttpBinding) so that the service can be called from a Silverlight web application.

    The problem I have is that the silverlight app is unable to call the WCF service (while debugging in VS). That is, the WCF service is hosted by VS and the silverlight app is contained in an ASP.Net web site also hosted by VS. The domain of the asp.net app is "localhost:1592" while the WCF service is being hosted at "localhost:8731". Therefore, I have a cross-domain situation that needs to be overcome.

    I have a clientaccesspolicy.xml file and a crossdomain.xml file in my "C:\Inetpub\wwwroot" folder.

    clientaccesspolicy.xml contains:

    <?xml version="1.0" encoding="utf-8"?>
    <access-policy>
      <cross-domain-access>
        <policy>
          <allow-from>
            <domain uri="*"/>
          </allow-from>
          <grant-to>
            <resource path="/" include-subpaths="true"/>
          </grant-to>
        </policy>
      </cross-domain-access>
    </access-policy>

    crossdomain.xml contains:

    <?xml version="1.0"?>
    <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
    <cross-domain-policy>
      <allow-access-from domain="*" />
    </cross-domain-policy>

    Using the "Microsoft Service Trace Viewer", I can see that the WCF service does receive data from the console application (obviously - since this worked). However, the trace viewer indicates that the WCF service does not receive any data from the silverlight app.

    Using Fiddler, I can see that there seems to be a problem when the silverlight application (hosted by an ASP.Net app) attempts to make a call to the WCF service:

    GET http://localhost:1592/Silverlight01_Web/Silverlight01TestPage.aspx
    200 OK

    GET http://localhost:1592/Silverlight01_Web/ClientBin/Silverlight01.xap
    200 OK

    GET http://localhost:8731/clientaccesspolicy.xml
    400 Bad Request

    GET http://localhost:8731/crossdomain.xml
    400 Bad Request

    So, is the problem that something is having a problem obtaining the clientaccesspolicy.xml and crossdomain.xml files?

    In which case, any suggestions would be appreciated as to how I can get this working.

    Thanks.

  • Allen Chen – MSFT

    Allen Chen –...

    Star

    14215 Points

    1854 Posts

    Microsoft

    Re: Silverlight 2 and WCF - Protocol Error

    Jun 02, 2008 02:48 AM | LINK

    Hi:

      Client config file will not work in Beta 1. We shall explictly specify the Binding and EndpointAddress. Please check out our quickstart for more details:

    http://silverlight.net/Quickstarts/Remote/323aac2f-14cc-4dd8-bb40-fa2cb3c2e522.aspx

      In addition, please check if you can get the response when you request http://localhost:8731/clientaccesspolicy.xml

      I suggest you to create Asp.Net Web Application project to host Silverlight and set the port or use IIS Web Server via Properties->Web.

    Regards

    Sincerely,
    Allen Chen
    Microsoft Online Community Support

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • guylemar

    guylemar

    Member

    16 Points

    4 Posts

    Re: Silverlight 2 and WCF - Protocol Error

    Jun 05, 2008 06:13 AM | LINK

    Hi Allen, thanks for the reply.

     Following those instructions worked ok for me.

    The main difference between the instructions and what I had done, was that I created the WCF service project differently. I tried having a Windows Service with a WCF-service in it (where the WCF-service was in a class library).

    This seems conceptually similar to the architecture of the link you provided - just that I was trying to use a windows service to host the WCF instead of an ASP aplication. Is what I was trying to do possible/reasonable? That is, have a web-based silverlight application utilize a WCF service that's hosted by a windows service? The reason for this is that the WCF service is a "middle tier", so connecting to it directly from the silverlight application seems desirable.

    Thanks,

    Guy

  • Allen Chen – MSFT

    Allen Chen –...

    Star

    14215 Points

    1854 Posts

    Microsoft

    Re: Silverlight 2 and WCF - Protocol Error

    Jun 05, 2008 11:12 AM | LINK

    Hi:

      It's not that easy sine you have to provide the cross domain policy file. To solve this problem please try my sample here:

      Create Windows Service project, add App.config into it:

    App.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>

      <system.serviceModel>
        <services>
          <service name="Microsoft.ServiceModel.Samples.CrossDomainService">
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:7999/"/>
              </baseAddresses>
            </host>
            <endpoint address=""
                      binding="webHttpBinding"
                      contract="Microsoft.ServiceModel.Samples.ICrossDomain"  behaviorConfiguration="HttpEnableBehavior" />
     
          </service>
          <service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior" >
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:7999/ServiceModelSamples/service"/>
              </baseAddresses>
            </host>
            <!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModelSamples/service  -->
            <endpoint address=""
                      binding="basicHttpBinding"
                      contract="Microsoft.ServiceModel.Samples.ICalculator"/>
            <!-- the mex endpoint is explosed at http://localhost:8000/ServiceModelSamples/service/mex -->
            <endpoint address="mex"
                      binding="mexHttpBinding"
                      contract="IMetadataExchange" />
          </service>
        </services>
        <behaviors>
          <endpointBehaviors>
            <behavior name="HttpEnableBehavior">
              <webHttp/>
            </behavior>
          </endpointBehaviors>

          <serviceBehaviors>
     
            <behavior name="CalculatorServiceBehavior">
              <serviceMetadata httpGetEnabled="True"/>
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>

      </system.serviceModel>
    </configuration>

     Modify the code in Program.cs:

    using System;
    using System.ComponentModel;
    using System.Configuration;
    using System.Configuration.Install; // in System.Configuration.Install.dll
    using System.ServiceModel;
    using System.ServiceProcess;
    using System.ServiceModel.Web;
    using System.IO;
    using System.ServiceModel.Description;
    using System.ServiceModel.Channels;
    using System.Xml; // in System.ServiceProcess.dll

    namespace Microsoft.ServiceModel.Samples
    {
        // Define a service contract.
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface ICalculator
        {  

            [OperationContract]
            double Add(double n1, double n2);
            [OperationContract]
            double Subtract(double n1, double n2);
            [OperationContract]
            double Multiply(double n1, double n2);
            [OperationContract]
            double Divide(double n1, double n2);
        }
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface ICrossDomain {
            [OperationContract]
            [WebGet(UriTemplate = "clientaccesspolicy.xml")]
            Message ProvidePolicyFile();

        }
        // Implement the ICalculator service contract in a service class.

        public class CalculatorService : ICalculator
        {
            // Implement the ICalculator methods.
            public double Add(double n1, double n2)
            {
                double result = n1 + n2;
                return result;
            }

            public double Subtract(double n1, double n2)
            {
                double result = n1 - n2;
                return result;
            }

            public double Multiply(double n1, double n2)
            {
                double result = n1 * n2;
                return result;
            }

            public double Divide(double n1, double n2)
            {
                double result = n1 / n2;
                return result;
            }
        }
        public class CrossDomainService : ICrossDomain {


            private XmlReader MakeXml()
            {

     

                TextReader reader = new StringReader(@"<?xml version='1.0' encoding='utf-8'?>
    <access-policy>
      <cross-domain-access>
        <policy>
          <allow-from>
            <domain uri='*'/>
          </allow-from>
          <grant-to>
            <resource path='/' include-subpaths='true'/>
          </grant-to>
        </policy>
      </cross-domain-access>
    </access-policy>");

                return XmlReader.Create(reader);

            }

     

            public Message ProvidePolicyFile()
            {

                XmlReader xmlReader = MakeXml();

                return Message.CreateMessage(MessageVersion.None, "", xmlReader);

     

            }

        
        }
        // Windows Service class which inherits from ServiceBase
        // and contains the application entry point.

        public class CalculatorWindowsService : ServiceBase
        {

            public ServiceHost serviceHost = null;
            public ServiceHost serviceHost2 = null;

            public static void Main()
            {
                ServiceBase.Run(new CalculatorWindowsService());
               
            }

            public void CalculatorService()
            {
                ServiceName = "WCFWindowsServiceSample";
            }

            // Start the Windows service.
            protected override void OnStart(string[] args)
            {
                try
                {
                    if (serviceHost != null)
                    {
                        serviceHost.Close();
                    }
                    if (serviceHost2 != null)
                    {
                        serviceHost2.Close();
                    }

                    // Create a ServiceHost for the CalculatorService type and
                    // provide the base address.
                    serviceHost = new ServiceHost(typeof(CalculatorService));
                    serviceHost2 = new ServiceHost(typeof(CrossDomainService));
                    // Open the ServiceHostBase to create listeners and start
                    // listening for messages.
                    serviceHost.Open();
                    serviceHost2.Open();
                }
                catch(Exception ex){
                    //To log the error
                    System.IO.FileStream fs;
                    if (System.IO.File.Exists(@"C:\Log.txt"))
                    {
                        fs = new FileStream(@"C:\Log.txt", FileMode.Append);
                    }
                    else fs = new FileStream(@"C:\Log.txt", FileMode.OpenOrCreate);
                    Byte[] bContent = System.Text.Encoding.GetEncoding("gb2312").GetBytes(ex.Message + "\r\n");
                    fs.Write(bContent, 0, bContent.Length);
                    fs.Close();
              

                }

     

            }

            // Stop the Windows service.
            protected override void OnStop()
            {
                if (serviceHost != null)
                {
                    serviceHost.Close();
                    serviceHost = null;
                }

     if (serviceHost2 != null)
                {
                    serviceHost2.Close();
                    serviceHost2 = null;
                }

            }
        }

        // Provide the ProjectInstaller class which allows
        // the service to be installed by the Installutil.exe tool

        [RunInstaller(true)]
        public class ProjectInstaller : Installer
        {
            private ServiceProcessInstaller process;
            private ServiceInstaller service;

            public ProjectInstaller()
            {
                process = new ServiceProcessInstaller();
                process.Account = ServiceAccount.LocalSystem;
                service = new ServiceInstaller();
                service.ServiceName = "WCFWindowsServiceSample3";
                Installers.Add(process);
                Installers.Add(service);
            }
        }
    }

    Install and start the Windows Service:

    http://msdn.microsoft.com/en-us/library/ms733069.aspx

     

    Add service reference in Silverlight project:

     public Page()
            {
                InitializeComponent();
                BasicHttpBinding binding = new BasicHttpBinding();
                EndpointAddress ed = new EndpointAddress("http://localhost:7999/ServiceModelSamples/service");
                ServiceReference3.CalculatorClient proxy = new SilverlightApplication1.ServiceReference3.CalculatorClient(binding,ed);
                proxy.AddCompleted += new EventHandler<SilverlightApplication1.ServiceReference3.AddCompletedEventArgs>(proxy_AddCompleted);
                proxy.AddAsync(1, 2);    

                   }

            void proxy_AddCompleted(object sender, SilverlightApplication1.ServiceReference3.AddCompletedEventArgs e)
            {

    //Breakpoint here. result should be 3.

            }

    Regards

    Sincerely,
    Allen Chen
    Microsoft Online Community Support

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • guylemar

    guylemar

    Member

    16 Points

    4 Posts

    Re: Silverlight 2 and WCF - Protocol Error

    Jun 05, 2008 11:08 PM | LINK

    Thanks very much for that Allen.

    I'll try that out and let you know how I get on.

  • guylemar

    guylemar

    Member

    16 Points

    4 Posts

    Re: Silverlight 2 and WCF - Protocol Error

    Jun 06, 2008 06:10 AM | LINK

    Hi Allen,

    Thanks very much for the previous post - that got me 99% of the way there.

    I just had to alter the OnStart( ) and OnStop( ) methods of CalculatorWindowsService so that the CrossDomainService was (also) started and stopped. Without this, I still received the 404 error.

    Thanks again,

    Guy

  • cncolder

    cncolder

    Member

    45 Points

    29 Posts

    Re: Re: Silverlight 2 and WCF - Protocol Error

    Jun 30, 2008 03:53 AM | LINK

     Silverlight 2 beta2 cannot reference webHttpBinding [:'(]




    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    http://www.ViTarn.com/
  • SilverlightGeek

    SilverlightGeek

    Member

    20 Points

    10 Posts

    Re: Re: Silverlight 2 and WCF - Protocol Error

    Jul 09, 2008 04:01 PM | LINK

    I see the same on my end. I wrote a great WCF Rest compatible service using webHttpBinding and it worked great in Silverlight 2 Beta 1. Now that I've upgraded to Silverlight 2 Beta 2 it looks as though I can not use this Binding type anymore!??! 

    webHttpBinding was great because I could easily switch the encoding between XML or JSON. Has ANYONE found a way to use a webHttpBinding WCF service in Silverlight 2 Beta 2? Anyone???

  • harsha_hs

    harsha_hs

    Member

    44 Points

    21 Posts

    Re: Silverlight 2 and WCF - Protocol Error

    Apr 08, 2009 09:19 AM | LINK

     I am using Silverlight 2. I tried your sample, and services are running fine.

    I get calculator service when I type this URL: http://localhost:7999/ServiceModelSamples/service

    and I get clientaccesspolicy file when I type this URL: http://localhost:7999/clientaccesspolicy.xml

    But when I run my silverlight application, I get following error:

    An error occurred while trying to make a request to URI 'http://localhost:7999/ServiceModelSamples/service'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. Please see the inner exception for more details.

    But, I used Nikhil's Web Development Helper, I see that Silverlight app is getting 'clientaccesspolicy.xml' since it is giving 200.

    I don't know what is the problem? Is it because even Silverlight 2 Doesn't support webhttpbinding? If so what is the workaround?

  • HarshBardhan

    HarshBardhan

    Star

    10118 Points

    1749 Posts

    Re: Silverlight 2 and WCF - Protocol Error

    Apr 09, 2009 11:32 AM | LINK

     specify binding as basichttp binding and check.

    Mark as answer if this post answered your question.

    Harsh Bardhan