Workaround to adding Service Reference to Windows Phone 8.1 (Runtime app)
I’ve got lots of queries recently from fellow developers about their inability to consume WCF services from Windows Phone 8.1 Runtime app. Apparently, adding a service reference (for WCF Services) to the project via Visual Studio is currently available for Windows Phone 8.0, Windows Phone 8.1 Silverlight and Windows 8.1 projects but not for Windows Phone 8.1 Runtime project.
How to consume WCF service / add service reference to Windows Phone 8.1:
Scenario 1: Building Windows Phone 8.1 Silverlight
Just right click on reference and click ‘Add Service reference’ and proceed with the way you are used to.
Scenario 2: Building Windows Phone 8.1 Runtime app / Universal app
For this one, a direct way doesn’t seem to be available in the time being, a workaround exists though that I thought I should share. To sum it up, you need to add a REST endpoint to your WCF service and then make REST calls from your Windows Phone app.
Here’s a quick tutorial from scratch
2.1 Creating a Windows Phone 8.1 Runtime app and a WCF Service Application:
1. In my SUPER SIMPLE example I created a blank app (Windows Phone) called “Consume WCF from WP8.1 Sample” and added a WCF Service Application to my solution and called it “REST WCF Service”
2. In the IService1.cs file, I only kept the below Operation Contract and removed the parameters for simplicity
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData();
// TODO: Add your service operations here
}
3. In the Service1.svc.cs file, update the Service1 class that implements the new interface to be as below:
public class Service1 : IService1
{
public string GetData()
{
return "WCF Service";
}
}
2.2 In Just 2 Steps, Expose a REST interface of our ‘REST WCF Service’ to be able to call it from Windows Phone 8.1 Runtime:
Step1:
Add the WebGetAttribute and WebInvokeAttribute to your OperationContract as in Line 6 the below example:
1: [ServiceContract]
2: public interface IService1
3: {
4:
5: [OperationContract]
6: [WebGet(UriTemplate = "GetData")]
7: string GetData();
8:
9: // TODO: Add your service operations here
10: }
Step2:
It’s time to put the final touch to the WCF Service. To make it RESTful, we need to update the configuration ‘web.config’ file by adding endpoint behavior as in Lines 15-21 then Update the endpoint by changing the binding to webHttpBinding and finally point to the behavior created by adding the behviorConfiguration to the endpoint node as in Lines 2-15
1: <system.serviceModel>
2: <!--UPDATE the ENDPOINT by Changing the binding to webHttpBinding-->
3: <!--POINT to the endpointBehavior Created below by ADDing behaviorConfiguration to the endpoint node-->
4: <services>
5: <service behaviorConfiguration="MyServiceBehavior" name="REST_WCF_Service.Service1">
6: <endpoint address="" binding="webHttpBinding" behaviorConfiguration="web" contract="REST_WCF_Service.IService1">
7: <identity>
8: <dns value="localhost"/>
9: </identity>
10: </endpoint>
11: <endpoint address="max" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
12: </service>
13: </services>
14: <behaviors>
15: <!--BEGIN ADD ENDPOINT BEHAVIOR-->
16: <endpointBehaviors>
17: <behavior name ="web">
18: <webHttp />
19: </behavior>
20: </endpointBehaviors>
21: <!--END of ADD ENDPOINT BEHAVIOR-->
22: <serviceBehaviors>
23: <behavior name="MyServiceBehavior"> <!--ADDED MyServiceBehvior-->
24: <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
25: <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
26: <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
27: <serviceDebug includeExceptionDetailInFaults="false"/>
28: </behavior>
29: </serviceBehaviors>
30: </behaviors>
31: <protocolMapping>
32: <add binding="basicHttpsBinding" scheme="https" />
33: </protocolMapping>
34: <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
35: </system.serviceModel>
--> Your WCF Service is now RESTful (i.e. can be called from Windows Phone 8.1 Runtime app)
2.3 Call RESTful WCF Service from Browser or Windows Phone 8.1 Runtime app
You can test your servicefrom the browser or your Windows Phone 8.1 Runtime app to see the result.
Browser:
I launched it in Internet Explorer and my URL was https://localhost:18362/Service1.svc. Now, I can point to my REST url by appending the method name that I specified in the UriTemplate attribute (GetData) to my .svc uri –> https://localhost:18362/Service1.svc/GetData
You should get the following:
Phone:
1: private async void CallService() 2: { 3: HttpClient httpClient = new System.Net.Http.HttpClient(); 4: HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:18362/Service1.svc/GetData"); 5: HttpResponseMessage response = await httpClient.SendAsync(request); 6: string data = await response.Content.ReadAsStringAsync(); 7: var dialog = new MessageDialog(data); 8: await dialog.ShowAsync(); 9: 10: }
You should get the following:
You may download the full solution from here.
I hope this was helpful.
Kindly share with your developers and community.
Please feel free to subscribe to my blog or follow me on twitter for alerts on posts.
Mohamed Yamama,
@m_yamama
[Please read the DISCLAIMER for this blog here.]
Comments
Anonymous
September 05, 2014
Tried to remake this in my own application because it was exactly what I was looking for now that normal service references are out of the Picture. BUT, I couldn't get it to Work. The messagebox was just an empty string and when I debug the response returns 404 even though I can open the url http://localhost:18362/Service1.svc/GetData and get the same result as you. I even tried downloading ur sample and run that instead. Same story. ;(Anonymous
September 05, 2014
Forget what I wrote. You don't want to hear the reason. Just thank you a lot for this :)Anonymous
September 30, 2014
Hi, Flemming When debugging the response return 404 not found, could you plese helpe meAnonymous
November 03, 2014
I created the service reference in VS2012 then opened the solution in VS2013 I have all method, but calling any method doesn't nothing return.Anonymous
November 11, 2014
Being new to Windows 8.1 Phone development I've found this really helpful. I have the example running well on my machine but have some questions... Does the WCF web service get installed on the phone along with the app? How do I pass parameters through to the web service? I am assuming this would also handle complex data types?Anonymous
November 14, 2014
WOW. Great tutorial works fine in my case. Thanks. :)Anonymous
December 17, 2014
Hi, i try to turn your example on my Nokia Lumia 830 and i have the response returns "404 Not Found". I don't know why. ThanksAnonymous
February 26, 2015
Flemming! I have the same problem! What am I missing??? you found it...Anonymous
March 01, 2015
in the localhost url, give ur port number instead of 18362Anonymous
April 04, 2015
how to pass parameters to this code?Anonymous
April 09, 2015
I have used my own port in the localhost Url but still I'm not receiving the response. 404 Not Found, @Fleming - what did you do man?Anonymous
April 09, 2015
I tried hosting the service on the IIS on a server. Now I'm getting status code 504 - Gateway Timeout. But I'm able to browse the url and data is coming in the XML format.Anonymous
June 02, 2015
So, any ideas how we can access our services ?? I have the same problemAnonymous
June 05, 2015
but how can i RETURN just the Message and not the all stuffAnonymous
July 07, 2015
Thanks very much for this rare tutorial ! I just read that Microsoft recommands using Windows.Web.Http instead of System.Net.Http from Windows 8.1 : msdn.microsoft.com/.../hh781239.aspx The code of function CallService would be shorter then : <Code> private async void CallService() { HttpClient httpClient = new HttpClient(); string data = await httpClient.GetStringAsync(new Uri("http://localhost:60347/FilmService.svc/GetData")); var dialog = new MessageDialog(data); await dialog.ShowAsync(); } </Code>