none
Moving application with Silverlight WCF service from development machine to server

    Question

  • Ok, I've been beating my head against this long enough.

    I developed a application with a Silverlight WCF service locally hosted in it.  It works fine on my development machine.  I now need to deploy it to a Web Server, but I can't find a way to configure the service so that it is recognized.

     How does one configure a WCF service so that it works outside of the development machine?

    Monday, December 21, 2009 3:47 PM

Answers

  • My solution is only a fast fix, but isn't the best solution as Michel points out, the problem is when you do changes to the SL project and build it, the old .xap file can be replaced with a new one.

    But about your problem, try to use the URL in a browser and see if you will get access to the service. The SL WCF uses basic HTTP binding, so enable anonymous access for the virtual directory or app where you Service is hosted. You also need a policy file: http://timheuer.com/blog/archive/2008/04/06/silverlight-cross-domain-policy-file-snippet-intellisense.aspx.

    Tuesday, December 22, 2009 4:18 AM
  • What you have is the standard <Object> tag rather then using an asp:Silverlight tag, this is easy to alter and will give you access to your Silverlight object via CodeBehind.

    In your Web Project add a reference to System.Web.Silverlight

    In the page that hosts your Silverlight control add the following Register tag to the top:

     

    <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>

     Then replace your <object ...... > code with the standard ASP.NET Control entry like this:

    <asp:Silverlight ID="Xaml1" Source="~/ClientBin/SilverlightApplication.xap" runat="server" 
            Height="100%" Width="100%">
            </asp:Silverlight>

     Make sure that "Source=" points to the correct location of your Silverlight xap file. You should now be albe to implement the steps outlined in my previous post.

    Hope this helps

    Tuesday, December 22, 2009 3:59 PM
  • Hi gisprogrammer,

    Check to make sure that your server has been correctly configured to serve up .svc files.

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

    In your code it doesn't look like your making a cross domain service call, so you shouldn't have to worry about any policy files.

     

    Tuesday, December 22, 2009 4:08 PM

All replies

  • Rename the .xap file in clientbin to .zip, open it, change the end point in the config file to the server, rename the .zip file back to .xap.. Hope this will help..

    Monday, December 21, 2009 3:49 PM
  • if your Silverlight-enabled WCF service is hosted within a web application then deployment of the service is straight forward, however connection to the production location of the service from within your silverlight application is something that you need to plan for, fortunitely its pretty easy to set up so that you can quickly update the production/stagging/dev location of the web service(s) via a config file app setting and the Silverlight InitParameters.

    Lets look at an example that will make more sense:

    Problem Caused by:

    I have a WCF service named "MyService.svc" located in my website project. My Silverlight project has a Service Reference to this WCF web service, whose endpoint is located at http://localhost:8801/MyService.svc

    From within my Silverlight project I new up a Client in order to call the methods exposed by MyService.svc, this is accomplished by doing something similiar to the following:

     

    var MyClient = new MyWebSiteService.MyServiceClient(); //where MyWebSiteService is the name of the Service Reference I created in my Silverlight project by right click on Service References and selecting the "Add Service Reference" option.
     

    This is where you are going to have an issue, the issue that you are reporting here. The problem is that calling the default ".MyServiceClient()" will return a client that points to the web service end-point we used when originally add the Service Reference (in this case that would be http://localhost:8801/ ) which is NOT what we want and exactly why it works fine on your Dev machine but doesn't work when we publish it to another location.

    Solution:

    Here is what we are going to do to resolve this issue. We are going to store in our Websites Web.Config file the base address for our web service (so when we are working in dev this will still be http://localhost:8801 but when we move to Production we will update the AppSettings to have the live URL such as http://www.MyCoolWebSite.com ). In your Web Sites Web.Config file, under the appSettings node, enter the following:

     

    <add key="WebServicesUrlBase" value="http://localhost:8801"/>
     

     

    Now in the page that holds the declaration of your Silverlight app we need to pass this parameter into the Silveright app via the InputParams. Lets assume our Silverlight app is located in our Websites "Default.aspx" page like the following:

    <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightInterface.xap">
    </asp:Silverlight>

     Then in the code-behind file (Default.aspx.cs) we would access our appSetting and pass it into the control:

    Xaml1.InitParameters = string.Format("WebServicesUrlBase={0}", System.Configuration.ConfigurationManager.AppSettings["WebServicesUrlBase"]);

     Then in the App.xaml.cs file in our Silverlight Application we can access and store the WebServicesUrlBase for use by our service clients:

    private void Application_Startup(object sender, StartupEventArgs e)
            {
                //Call the Web Service to get the User Data 
                if (e.InitParams.ContainsKey("WebServicesUrlBase"))
                {   //add a Static global variable named WebServiceUrlBase that is of type string, store into it the parameter value passed to us
                    App.WebServicesUrlBase = e.InitParams["WebServicesUrlBase"];
                }

     

    Now add a Class file (.cs) to your project, I call mine Helpers.cs, that will hold a static method we will call which will return to us a newly created Client() object which uses the WebServiceUrlBase we stored.

            public static MyWebsiteService.MyServiceClient RetreiveMyServiceClient()
            {            
                var Address = App.WebServicesUrlBase;
                var EndPointAddress = new System.ServiceModel.EndpointAddress(new Uri(string.Format("{0}/MyService.svc", Address)).AbsoluteUri); 
                return new MyWebsiteService.MyServiceClient("*", EndPointAddress);
            }

     Now, everywhere in your Silverlight application that makes a call to " = new MyWebsiteService.MyServiceClient();" needs to be replaced with " = Helpers.RetreiveMyServiceClient();"

    Then when you move the site to production just update the "appSetting" in your Web Applications Web.config file to point to the correct URL of the web service and everything will work properly.

    Please mark this as the "Answer" if it actually is the answer you were looking for.

    Hope this help

    Monday, December 21, 2009 4:37 PM
  • I can change the .xap file to a .zip file, change the config file, but renaming the .zip file back to a .xap file doesn't work.  It becomes a .xap.zip file, and not surprisingly the entire application crashes.  Is there a trick to changing the file back to a .xap file?

    Thanks.

    Monday, December 21, 2009 5:10 PM
  • You really should implement the plan I posted above for easily moving between environments as renaming and altering your .xap files is really not a practice that makes much sense.

    Monday, December 21, 2009 5:30 PM
  • I plan to.  I was just hoping that Frederick's plan would give me a quick fix.

    Monday, December 21, 2009 5:37 PM
  • My default.aspx file doesn't contain a tag like this:

    <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightInterface.xap"> </asp:Silverlight>

     Instead I have

    <body>

    <form id="form1" runat="server" style="height:100%; background:LightGray;">

    <div id="silverlightControlHost">

    <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">

    <param name="source" value="ClientBin/Census.xap"/>

    <param name="onError" value="onSilverlightError" />

    <param name="background" value="white" />

    <param name="minRuntimeVersion" value="3.0.40624.0" />

    <param name="autoUpgrade" value="true" />

    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">

    <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>

    </a>

    </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>

    </form>

    </body>

    I appreciate your effort, but I don't see how your solution can work when the tags are different. 

     

     

    Monday, December 21, 2009 6:13 PM
  • Frederick,

    Instead I tried editing the ServiceReference.ClientConfig file in VS, saving it, then copying it to my Server.  Thus the config file now reads:

    <endpoint address="http://agstest1/ClaritasService.svc"

    binding="customBinding" bindingConfiguration="CustomBinding_ClaritasService"

    contract="ClaratisDataServiceReference.ClaritasService" name="CustomBinding_ClaritasService" />

    where agstest1 is my server.  When I run it, the application comes in, but I get the following error: "The remote server returned an error: NotFound"

     

     

    Monday, December 21, 2009 6:18 PM
  • Let's try this again: 

    endpoint address="http://agstest1/ClaritasService.svc"

     

    Monday, December 21, 2009 6:20 PM
  • My solution is only a fast fix, but isn't the best solution as Michel points out, the problem is when you do changes to the SL project and build it, the old .xap file can be replaced with a new one.

    But about your problem, try to use the URL in a browser and see if you will get access to the service. The SL WCF uses basic HTTP binding, so enable anonymous access for the virtual directory or app where you Service is hosted. You also need a policy file: http://timheuer.com/blog/archive/2008/04/06/silverlight-cross-domain-policy-file-snippet-intellisense.aspx.

    Tuesday, December 22, 2009 4:18 AM
  • The cross policy file I have.  I know that works.

    When I try to access the service through a URL, I get the following error:

    HTTP Error 404.3 - Not Found

    The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

    I'm new to web programming, so I have no idea what they mean by adding a handler. The help is appreciated.

     

     

     

    Tuesday, December 22, 2009 10:34 AM
  • What you have is the standard <Object> tag rather then using an asp:Silverlight tag, this is easy to alter and will give you access to your Silverlight object via CodeBehind.

    In your Web Project add a reference to System.Web.Silverlight

    In the page that hosts your Silverlight control add the following Register tag to the top:

     

    <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>

     Then replace your <object ...... > code with the standard ASP.NET Control entry like this:

    <asp:Silverlight ID="Xaml1" Source="~/ClientBin/SilverlightApplication.xap" runat="server" 
            Height="100%" Width="100%">
            </asp:Silverlight>

     Make sure that "Source=" points to the correct location of your Silverlight xap file. You should now be albe to implement the steps outlined in my previous post.

    Hope this helps

    Tuesday, December 22, 2009 3:59 PM
  • Hi gisprogrammer,

    Check to make sure that your server has been correctly configured to serve up .svc files.

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

    In your code it doesn't look like your making a cross domain service call, so you shouldn't have to worry about any policy files.

     

    Tuesday, December 22, 2009 4:08 PM
  • Clint,

    I've come to the same conclusion.  Thanks for the link.  I'll see if I can't get that straightened out then I'll look at Michael's suggestion.

    Thanks.

    Tuesday, December 22, 2009 5:10 PM
  • Or you can just pass the InitParams inside the silverlight <object> tag

    http://betaforums.silverlight.net/forums/p/115304/292032.aspx 

    Monday, January 04, 2010 4:53 PM
  • I had the same problem - turned out wcf was not completely installed. After installing it, everything worked fine:

    The information from this website provided the solution:

    http://blogs.msdn.com/davidwaddleton/archive/2007/11/02/wcf-and-404-3-errors.aspx

    Saturday, February 06, 2010 11:49 AM
  • Hi,

     My Silverlight app is "hosted" in a WPF application that uses RESTful api to enable clients to access it.  I don't have asp anything yet I too am trying to solve the hard coded machine name in the config file.  Do these InitParams work when your "web server" simply returns the XAP file?

     Thanks,

    John

    Friday, February 12, 2010 12:47 PM
  • I do not have a System.Web.Silverlight assemble for which I can make a reference even though I belive I have the latest Microsoft Silverlight 3 SDK installed. Do I need to install something else also?

    Wednesday, February 24, 2010 2:28 PM
  • The System.Web.Silverlight assembly was depricated after Silverlight 2 and is not included in the Silverlight 3 install. The preferred method of embedding your Silverlight control into the page is marked below. For now simply remove the
    <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightInterface.xap">
    </asp:Silverlight>

     and replace it with the following (Notice how we pass in the InitParams):

    <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="1000" height="565">
                <param name="source" value="ClientBin/SilverlightInterface.xap" />
                <param name="windowless" value="true" />
                <param name="background" value="Transparent"/>
                <param name="minRuntimeVersion" value="3.0.40624.0" />
                <param name="autoUpgrade" value="true" />
                <param name="initparams" value="<%= string.Format("WebServicesUrlBase={0}", System.Configuration.ConfigurationManager.AppSettings["WebServicesUrlBase"]) %>" />
                <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" mce_href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none">
                    <img src="http://go.microsoft.com/fwlink/?LinkId=108181" mce_src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" />
                </a>
            </object>
     Sorry for any confusion I may have caused.
    Wednesday, February 24, 2010 4:45 PM
  • Hi Michael,

    I couldn't make it work until I used the EndpointAddress constructor overload accepting "endpointConfigurationName" as its 1st parameter. And I think it really should not work without this parameter - or how should it understand which contract must be used?! Does your implementation really work without this parameter?!!!

    Besides, I'm still not satisfied with the suggested workaround. In fact, we duplicate things and make a hardcode in our codebehind. I think it's not a good practice. At the same time, it seems that there are no other solutions, and I refuse to believe in this fact. What we all would like to have is the possibility to associate endpoints' addresses with the current build configuration of the SL web-project so that "Debug" will assume http://localhost:port/blah and "Release" - http://ourdomain/blah (the production address). But I can't figure out how to do that :-(

    Tuesday, March 02, 2010 7:36 AM
  • in your silverlight project, where ever you need to get a Client to your web service(s) you call a method (which you have created) that would be similiar to the following:

     

            public static MyWebsiteService.MyServiceClient RetreiveMyServiceClient()
            {            
                var Address = App.WebServicesUrlBase;
                var EndPointAddress = new System.ServiceModel.EndpointAddress(new Uri(string.Format("{0}/MyService.svc", Address)).AbsoluteUri); 
                return new MyWebsiteService.MyServiceClient("*", EndPointAddress);
            }

     so it would look something like this:

    var Client = Classes.Helpers.RetreiveMyServiceClient();

     Notice that in the method it grabs the "Address" from the App.WebServicesUrlBase (you could name this anything you wanted), which is just a globally available Public Static string value you created in your App.xaml.cs file. You get the base URL of your web services into your Silverlight project by passing it in as an initParam and then, in the Application_Startup event located in App.xaml.cs, you grab it out of the initParam collection and store it into this global string variable.  

    The benefits of this is approach is that you can set in your Website AppConfig setting the location of the web services (so localhost, a stagging server, a production server, whatever you want) and pass it to your Silverlight project. Then this value will be used any time you need to create a Client object in order to call its web services. Moving from Dev, to Test or Prod simply requires changing the value in your AppSettings of the Web.Config file.

    Tuesday, March 02, 2010 6:17 PM
  • I understand this quite well, and I followed this recommendation accurately. But I received errors until I modified this line

    return new MyWebsiteService.MyServiceClient("*", EndPointAddress);
    to receive real endpoint name as its 1st parameter. My Web.config contains the following:
    <service behaviorConfiguration="RMS.Web.DataServices.ClientAccountsBehavior"
      name="RMS.Web.DataServices.ClientAccounts">
        <endpoint name="RMS.Web.DataServices.ClientAccounts.EndPoint" address="" binding="customBinding" bindingConfiguration="customBinding0"
            contract="RMS.Web.DataServices.IClientAccounts" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>

    and the "ServiceReferences.ClientConfig" file - the following:

    <endpoint address="http://localhost:3272/DataServices/ClientAccounts.svc"
        binding="customBinding" bindingConfiguration="RMS.Web.DataServices.ClientAccounts.EndPoint"
        contract="ClientAccounts_ServiceReference.IClientAccounts"
        name="RMS.Web.DataServices.ClientAccounts.EndPoint" />
    so this 1st parameter was set to "RMS.Web.DataServices.ClientAccounts.EndPoint". And it seems that it is really necessary to supply the endpoint name - otherwise how can the contract be resolved ("RMS.Web.DataServices.IClientAccounts")?! That is what I'm actually asking about!

    This is how the service reference is created in my case:

    public static class ServiceRefFactory
    {
        public static ClientAccountsClient GetClientAccountsService()
        {
            return GetServiceRef<ClientAccountsClient>(
                "ClientAccounts.svc", "RMS.Web.DataServices.ClientAccounts.EndPoint");
        }
        private static T GetServiceRef<T>(string serviceName, string endPointConfigName) where T : class
        {
            EndpointAddress endPointAddress =
                new EndpointAddress(
                    new Uri(string.Format("{0}/{1}", App.WebServicesUrlBase, serviceName)).AbsoluteUri);
            object[] p = new object[] { endPointConfigName, endPointAddress };
            return System.Activator.CreateInstance(typeof(T), p) as T;
        }
    }

    I understand that all service details (including endpoint info - and contract as well) is included in the "ServiceReferences.ClientConfig" file which is generated by the WCF Proxy Generation Tool. But when we use any of the parameterized constructors (of the service reference) instead of the default one, aren't we saying "Do not look into the ServiceReferences.ClientConfig file and create service reference from scratch with the supplied parameters"?! Or the asterisk you use instead of the real endpoint name has some magic?!

    Thank you.

    Wednesday, March 03, 2010 1:55 AM
  • Hello, As u say , me too creating object of WCFService "LoginInfo" created in ASP.NET MVC, as var obj = Resolve(Of LoginInfoClient)() whenever i called any function of this service it automatically create a new instance of service in ASP.NET MVC. Now i want this should not be done. I want when i create instance of serviceclient then only new instance of service should be created. Thanks in advance.
    Friday, April 30, 2010 7:06 AM