by Laurent Bugnion via Silverlight on 12/7/2011 9:36:33 PM
I was recently made aware of a couple of people having issues with WCF services (or ASP.NET applications) when using the MVVM Light project template for Silverlight. There is a blog post and a StackOverflow question, so what exactly is happening there?
Well in fact it is pretty simple when you know how Silverlight connects to web services. Due to the security model of Silverlight, the application cannot connect to a web site if it is not originating of this very website. In laymen’s terms, it means that the application can only connect to a web server if it also comes from the same webserver. For example, if the Silverlight application is served by http://www.galasoft.com, it won’t be able to connect to, say, http://www.cnn.com without getting an exception. We talk about cross-domain access restrictions.
Of course there are ways around that, for instance a website can specifically give access to Silverlight applications through a configuration file.
In the case that concerns us, it is exactly what is happening. You see, the MVVM Light Silverlight project template creates a Silverlight application without an ASP.NET host. I didn’t add one because I didn’t want to complicate the template too much. And also, to be honest, because adding a web project is super easy, but of course only if you know how to do, and this is exactly what we will do here!
The steps to create the application and the WCF service are as follows:
public class DataService : IDataService { public void GetData(Action<DataItem, Exception> callback) { var client = new ServiceReference1.Service1Client(); client.GetDataCompleted += ClientGetDataCompleted; client.GetDataAsync(1234, callback); } void ClientGetDataCompleted( object sender, ServiceReference1.GetDataCompletedEventArgs e) { var callback = e.UserState as Action<DataItem, Exception>; if (callback == null) { return; } if (e.Error != null) { callback(null, e.Error); } callback(new DataItem(e.Result), null); } }
This code uses an asynchronous service call pattern where the callback (a reference to a method passed as Action by the caller) is saved in the service call. Then when the asychronous call returns (in the Completed event), the callback is retrieved from the UserState. If an error occurred, the callback can be used to pass this error to the caller. Otherwise, a new DataItem class is created and passed to the called.
Details about this pattern can be found in my talks Understanding the MVVM pattern and Deep Dive MVVM.
If you run the application now (making sure that the MVVM Light project is selected as Startup Project), you will first see a warning dialog and then an exception. What happened?
What happened here is exactly the cross-domain issue I mentioned: The Silverlight application is not explicitly hosted into a web application, so Visual Studio is using an auto-generated HTML page instead, and running it from the embedded web server (“Cassini”). In fact, unless you explicitly specified otherwise, the test page is run in “file mode” instead of HTTP mode. The URI in the web browser window starts with C:\ for instance, instead of http://.
In those conditions, the access to the WCF service is (justly) denied, and you get a security exception.
In order to correct the error, you can either add a cross-domain policy file to your WCF application, or host the Silverlight application in the same web project as the WCF service. Let’s do that now:
This creates two new files in your WCF Service application: One is suffixed TestPage.html and the other is suffixed TestPage.aspx. We typically don’t need the ASPX one so you can safely delete it.
By doing this, we force Visual Studio to serve the HTML page and the Silverlight application from the same URL as the WCF Service, and to serve it as HTTP. This is possible because a WCF Service application is nothing else than an ASP.NET web server running WCF. So the same web server can deliver HTML, Silverlight and of course WCF.
If you run the application now, you will see the following result:
Note that the warning shown earlier will still appear, but it is really just a warning, and you can safely turn it off. Just remember the cross-domain restriction when you publish your Silverlight application to another web server!
Success, we hit the WCF service and returned with a valid result! In fact, you can verify by placing breakpoints in the DataService.GetData method on the client, and in the Service1.GetData method on the server. Then press F5 to run the application in Debug mode and notice how you can easily debug both the client and the server at the same time.
It is also possible to add a new MVVM Light application to an existing WCF Service application with the following steps (I am going a bit faster now, I am sure you will get it easily):
Hopefully the confusion around this is cleared now. In summary:
Note that the steps above can be used to add an MVVM Light application (or any Silverlight application) to any ASP.NET application, be it WCF Service application, ASP.NET MVC application or “classic” ASP.NET application.
Happy coding! Laurent
Original Post: MVVM Light template and WCF services (or any ASP.NET application for that matter)
The content of the postings is owned by the respective author. Silverlight Feeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on Silverlight Feeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.