Step By Step - Using Silverlight to Access a WCF Service Hosted In a Console Application

Posted by: Harsh Bardhan , on 9/29/2008, in Category Silverlight 2, 3, 4 and 5
Views: 165734
Abstract: In our projects, we often have a requirement of accessing Cross Domain Services in Silverlight. There are certain steps to be followed to able to do so. But what if the service is hosted in a console application or a windows service? In this article, we will follow a step by step approach and discuss how to create and consume a WCF Service hosted in a console application using Silverlight. We will also explore how to provide a Policy File at a given URI.
Step By Step - Using Silverlight to Access a WCF Service Hosted In a Console Application
 
Note: This article is written based on a pre-release version of Silverlight and could change in future.
In Silverlight, we often come across a very common requirement to consume Cross Domain Services. In order to support Cross Domain Services in Silverlight, we have to add 'Cross Domain Policy' file at the root of the web server. But if that Service is hosted in a Console Application or a WPF Application or a Windows Service, then how do we go about it? Where do we look for the Policy file?
In this article, we will discuss one approach to do so. We will be discussing the following steps in the order given below:
1) We will create a WCF Service to consume in a Console Project.
2) We will create another Service which will be used to provide the Policy File at that Particular URI.
3) We will edit our App.Config to be able to expose the service and will test run our Console Application.
4) We will then finally create a Silverlight Client Project which will consume this WCF Service.
Note: I will discuss a step by step approach for a Console Application. In a similar manner, you can also expose services from a Windows Service or WPF application.
Create a WCF Service to consume in a Console Project
 
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB.NET) > Select ‘Windows’ in the Project Types > Select ‘Console Application’ from Templates > Target type ‘.NET Framework 3.5’ > Type a name ‘AccessAServiceFromConsoleApplication’ (for C#) or ‘AccessAServiceFromConsoleApplicationVB’ (for VB) and location for the project and click ok. (Check the screenshot below)
Console Application 
 Step 2: If you have performed the above step correctly, you will be having only a Program.cs or Module1.vb file in this Project.  Now Right Click on the Project > click Add > click New Items. A window will appear displaying different templates. Select ‘WCF Service’ from the templates and name it as ‘MyService.cs’ or ‘MyService.vb’ (See Screenshot below). Now click on Add.
It will add two .cs (named IMyService.cs and MyService.cs) or .vb files (named IMyService.vb and MyService.vb)
MyService 
Step 3: We will now make some modifications to the [OperationContract] by changing the return type of default method (DoWork which will be added by default)   in the IMyService.cs or IMyService.vb interface from void to string. IMyService.cs or IMyService.vb will look like this:
C#
namespace AccessAServiceFromConsoleApplication
{
    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        string DoWork();
    }
}
VB.NET
<ServiceContract()> _
Public Interface IMyService
    <OperationContract()> _
    Function DoWork() As String
End Interface
Step 4: Since the ‘MyService’ class is implementing ‘IMyService’, we will make a small change in it also. In the ‘DoWork()’ method we will return a simple string.
MyService will look like this.
C#
namespace AccessAServiceFromConsoleApplication
{
public class MyService : IMyService
{
    public string DoWork()
    {
        return "This is A Sample From DotNetCurry.com";
    }  
}
}
 
VB.NET
Public Class MyService
    Implements IMyService
    Public Function DoWork() As String Implements IMyService.DoWork
        Return "This is A Sample From DotNetCurry.com"
    End Function
End Class
Step 5: Now Right Click on the Project > click Add > click New Items. A window will appear displaying different templates. Select “XML File” from the templates and name the xml file as ClientAccessPolicy.xml (See Screenshot below). Click Add.
Client Access Policy
Add the following contents to the ClientAccessPolicy.xml. You can get the content of this file from Microsoft’s site.
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
 <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
 </cross-domain-access>
</access-policy>
Before moving ahead, please build the solution and copy the ClientAccessPolicy.xml to the \bin directory of the Console Application. If you are unable to view the \bin folder, click on ‘Show All Files’ in the Solution Explorer.
Step 6: Now Right Click on Project > click Add > click New Items. A window will appear displaying different templates. Select WCF service from that and name that as CrossDomainService (See screenshot below). Click on Add.
Cross Domain Service
It will add two .cs files (named ICrossDomainService.cs and CrossDomainService.cs) or two .vb files (named ICrossDomainService.vb and CrossDomainService.vb)
Provide the Policy File at that Particular URI
 
Step 7: We will now change the default implementation of this service. Here we have to serve the cross domain file manually. To do so, we will use REST Service (Representational State Transfer) using WCF to provide the clientaccesspolicy.xml file. Using this approach, we will make our file available at a particular root URI.
Note: WCF 3.5 provides the new Web Programming Model that is made for building REST services. I have observed that doing REST style coding in WCF proves very handy.
Here our return type will be the message. So replace the contents of the ICrossDomainService.cs or .vb with the following. Our ICrossDomainService.cs or ICrossDomainService.vb will look like this.
C#
using System.ServiceModel.Web;
using System.ServiceModel.Channels;
 
 
namespace AccessAServiceFromConsoleApplication
{
    // NOTE: If you change the interface name "ICrossDomainService" here, you must also update the reference to "ICrossDomainService" in App.config.
    [ServiceContract]
    public interface ICrossDomainService
    {
        [OperationContract]
        [WebGet(UriTemplate = "ClientAccessPolicy.xml")]
        Message ProvidePolicyFile();
    }
}
 
VB.NET
Imports System.ServiceModel.Web
Imports System.ServiceModel.Channels
 
 
<ServiceContract()> _
 Public Interface ICrossDomainService
    <OperationContract(), WebGet(UriTemplate:="ClientAccessPolicy.xml")> _
    Function ProvidePolicyFile() As Message
End Interface
WebGet provides a mechanism to map an HTTP GET operation to a specific method. It will look for that method according to the URI specified in UriTemplate. So actually when we will type the <baseaddress> provided in our app.config file, followed by Uri Template string, it will execute this method.
For eg: You can try this here by typing http://localhost:8731/clientaccesspolicy.xml when your application is ready.
Note: For some reason, if you get the "The type or namespace name 'WebGetAttribute' could not be found", make sure you have added a reference to the System.ServiceModel.Web.
Step 8: Our CrossDomainService.cs or .vb will look like this. Here we are reading an Xml file and returning that.
C#
using System.Xml;
using System.ServiceModel.Channels;
 
namespace AccessAServiceFromConsoleApplication
{
    public class CrossDomainService : ICrossDomainService
    {
        public System.ServiceModel.Channels.Message ProvidePolicyFile()
        {
            FileStream filestream = File.Open(@"ClientAccessPolicy.xml", FileMode.Open);
            // Either specify ClientAccessPolicy.xml file path properly
            // or put that in \Bin folder of the console application
            XmlReader reader = XmlReader.Create(filestream);
            System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);
            return result;
        }
    }
}
 
VB.NET
Imports System.IO
Imports System.Xml
Imports System.ServiceModel.Channels
 
 
Public Class CrossDomainService
    Implements ICrossDomainService
    Public Function ProvidePolicyFile() As System.ServiceModel.Channels.Message Implements ICrossDomainService.ProvidePolicyFile
        Dim filestream As FileStream = File.Open("ClientAccessPolicy.xml", FileMode.Open)
        ' Either specify ClientAccessPolicy.xml file path properly
        ' or put that in \Bin folder of the console application
        Dim reader As XmlReader = XmlReader.Create(filestream)
        Dim result As System.ServiceModel.Channels.Message = Message.CreateMessage(MessageVersion.None, "", reader)
        Return result
    End Function
End Class
 
Note: Don’t forget to paste your ClientAccessPolicy.xml file in the \Bin folder, since in this sample, we have specified to look for the xml file in that location. We can also read the xml file using different methods; like by giving the absolute path, embedding the file etc.
Edit AppConfig to be able to expose the service will test run our Console Application
 
Step 9: Now we will modify our AppConfig. Do not forget to change the Binding to basicHttpBinding. Here we are specifying the Base address of CrossDomainService as "http://localhost:8731/" and base address of MyService as http://localhost:8731/AccessAServiceFromConsoleApplication/MyService.
If you observe carefully, both the services ‘base address root’ is the same. CrossDomainService will make our Policy file available at http://localhost:8731/clientaccesspolicy.xml". When our Silverlight application will try to access the Service, it will look in that URI as (http://localhost:8731/clientaccesspolicy.xml) and will get an access to it.
Note: We can change the Base Adresses in the app.config file for both the services, but make sure both the base address are pointing to the same root URI, i.e. “http://localhost:portnumber/” is the same.
The app.config will look similar to the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <behaviors>
      <serviceBehaviors>
        <behavior name="AccessAServiceFromConsoleApplication.MyServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="CrossDomainServiceBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration=
"AccessAServiceFromConsoleApplication.MyServiceBehavior"
        name="AccessAServiceFromConsoleApplication.MyService">
        <endpoint address="" binding="basicHttpBinding" contract="AccessAServiceFromConsoleApplication.IMyService">
 
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress=
/MyService" />
          </baseAddresses>
        </host>
      </service>
      <service name="AccessAServiceFromConsoleApplication.CrossDomainService">
 
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="webHttpBinding" contract=
"AccessAServiceFromConsoleApplication.ICrossDomainService" behaviorConfiguration="CrossDomainServiceBehavior"/>
      </service>
    </services>
 </system.serviceModel>
</configuration>
 
Step 10: The last step is to code the main method and open the service host to test if it is running. Write the following code in Program.cs or Module1.vb
C#
using System.ServiceModel;
 
namespace AccessAServiceFromConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost myserviceHost = new ServiceHost(typeof(MyService));
            ServiceHost crossDomainserviceHost = new ServiceHost(typeof(CrossDomainService));
            myserviceHost.Open();
            crossDomainserviceHost.Open();
            Console.WriteLine("Service is Running");
            Console.ReadLine();
        }
    }
}
 
VB.NET
Imports System.ServiceModel
 
Module Module1
    Sub Main()
        Dim myserviceHost As ServiceHost = New ServiceHost(GetType(MyService))
        Dim crossDomainserviceHost As ServiceHost = New ServiceHost(GetType(CrossDomainService))
        myserviceHost.Open()
        crossDomainserviceHost.Open()
        Console.WriteLine("Service is Running")
        Console.ReadLine()
    End Sub
End Module
 
The WCF Service is now ready. Run your application. If you have followed all the steps correctly up till here, you should see a message ‘Service is Running’ on the console. We will now create a Silverlight Client for accessing this WCF Service.
Create a Silverlight Client Project which will consume this WCF Service
 
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB.NET) > Select ‘Silverlight’ in the Project Types > from the templates, select ‘Silverlight Application’.
Step 2: Type a name (ConsumeWCFFromConsoleApplication) and location for the project and click ok. Choose the first option ‘Add a new Web to the solution for hosting the control’ and the project type as ‘Web Site’ and click OK. You will see that two projects are created: ConsumeWCFFromConsoleApplicationWeb and ConsumeWCFFromConsoleApplication.
Step 3: Now add a Service Reference of your Service .Right Click on Silverlight Project > click Add Service Reference >the ‘Add Service Reference’ dialog will appear. Give the Service URI mentioned in your App.Config of the console application. Paste it in Address Box > click Go.
Add a NameSpace. Here I have given the namespace as ‘ConsoleServiceReference’. Click on Ok (See Image Below)
Service Reference
Note: Make sure that when you are adding a reference to the service or you are running your Silverlight application, your Service is also running i.e. your Console Application should also be running.
Step 4: Now in your Page.Xaml.cs, refer to the Service. To test the data coming from our service, we will add a TextBlock whose ‘Text’ will be populated from our Service.
Page.Xaml will look like this:
<UserControl x:Class="ConsumeWCFFromConsoleApplication.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
 
    </Grid>
</UserControl>
The Page.Xaml.cs or Page.Xaml.vb will look like this:
C#
namespace ConsumeWCFFromConsoleApplication
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            ConsoleServiceReference.MyServiceClient consoleClient = new ConsumeWCFFromConsoleApplication.ConsoleServiceReference.MyServiceClient();
            consoleClient.DoWorkCompleted += new EventHandler<ConsumeWCFFromConsoleApplication.ConsoleServiceReference
.DoWorkCompletedEventArgs>(consoleClient_DoWorkCompleted);
           consoleClient.DoWorkAsync();
        }
 
        void consoleClient_DoWorkCompleted(object sender, ConsumeWCFFromConsoleApplication.ConsoleServiceReference
.DoWorkCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                TextBlock serviceText = new TextBlock();
                serviceText.Text = e.Result;
                LayoutRoot.Children.Add(serviceText);
 
            }
        }
    }
}
VB.NET
Namespace ConsumeWCFFromConsoleApplication
      Public Partial Class Page
            Inherits UserControl
            Public Sub New()
                  InitializeComponent()
                  Dim consoleClient As ConsoleServiceReference.MyServiceClient = New ConsumeWCFFromConsoleApplication.ConsoleServiceReference.MyServiceClient()
                  AddHandler consoleClient.DoWorkCompleted, AddressOf Of ConsumeWCFFromConsoleApplication.ConsoleServiceReference
.DoWorkCompletedEventArgs
                  consoleClient.DoWorkAsync()
            End Sub
 
            Private Sub consoleClient_DoWorkCompleted(ByVal sender As Object, ByVal e As ConsumeWCFFromConsoleApplication.ConsoleServiceReference
.DoWorkCompletedEventArgs)
                  If Not e.Result Is Nothing Then
                        Dim serviceText As TextBlock = New TextBlock()
                        serviceText.Text = e.Result
                        LayoutRoot.Children.Add(serviceText)
 
                  End If
            End Sub
      End Class
End Namespace
 
In the code above, when our service call completes, we are creating a TextBlock control and setting the Text property of that TextBlock to the message returned from the service. We finally add the TextBlock to the Children collection of Layout Root.
Run the application and you will be able to access the WCF Service hosted in Console Application using a Silverlight Client. I hope this article was useful and I thank you for viewing it.
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by (Will not be displayed) on Monday, September 29, 2008 5:02 AM
(Will not be displayed)
Comment posted by Nagel on Monday, September 29, 2008 5:51 AM
Good artilce. How is accessing wcf in silverlight different in console. is this not same way we do if wcf service is hosted in IIS also?
Comment posted by Nithi Lei on Monday, September 29, 2008 10:02 PM
Can we call WCF services hosted over https using Silverlight?
Comment posted by Harsh Bardhan on Tuesday, September 30, 2008 1:47 AM
Hi Nagel,
If we will host a Service in IIS than we can simply copy Paste
Policy file at Root.
But in case of Service hosted in Console/WPF/Windows services we have to serve that manually.Because there is no Root for Console Application.If you will check "Provide the Policy File at that Particular URI" Section of this Article you will see using Rest Services in WCF we are Providing that their.
Comment posted by Harsh Bardhan on Tuesday, September 30, 2008 10:05 AM
Hi Nithi,
Here you have to Configure Your Service as well as your client.
you Can check this video http://channel9.msdn.com/posts/mtaulty/Silverlight-Calling-HTTPS-Web-Services/
Comment posted by JaiPrakash on Tuesday, September 30, 2008 10:30 AM
Hello harshabardhan. the article is very good and easy to undersntand and i enjoyed it reading thankyou.

Jai Prakash
SE Developer
Comment posted by Nithi Lei on Wednesday, October 1, 2008 4:51 AM
Thanks for the link Harsh. Do you have any sample that calls https service using Silverlight?
Comment posted by Harsh Bardhan on Wednesday, October 1, 2008 9:04 AM
Hi Nithi,
I have not created a Sample for that.
Probably i will create that very soon and post that.
Comment posted by Jacob B. on Wednesday, October 1, 2008 9:56 PM
A very good article i appreciate the step by step approach.
Is there any way other than REST to return the cross domain policy file?
Comment posted by Harsh Bardhan on Thursday, October 2, 2008 5:38 AM
Hi Jacob,
For Services Hosted in console/Windows Services Rest is only Way.If it is Hosted in IIS you can directly Place Policy File.
Comment posted by Nikhil on Monday, October 6, 2008 9:44 PM
HarshBardhan - Can we make AJAX calls to the WCF service using silverlight?
Comment posted by Justin-Josef Angel on Monday, October 6, 2008 10:40 PM
Excellent! I love the way you piggy-banked on the server-side UriTemplate.
This is just brilliant:
   <OperationContract(), WebGet(UriTemplate:="ClientAccessPolicy.xml")> _
    Function ProvidePolicyFile() As Message

Way to go!
Comment posted by Harsh Bardhan on Tuesday, October 7, 2008 10:50 AM
Hi Nikhil,
You can use Javascript from silverlight and Call That Wcf SErvice.
Comment posted by Nikhil on Thursday, October 9, 2008 6:05 AM
Javascript is different technology and WCF is different right? How can i call WCF using js?
Comment posted by Steph on Sunday, October 12, 2008 5:02 PM
Hi Nikhil,
Great article ! I have been searching for this info for quite a long time. Happy to see it works now. THX !
Comment posted by Linda on Monday, October 13, 2008 8:06 AM
Steph: I guess you meant 'Harsh' and not nikhil :) The article has been written by Harsh.
Comment posted by Justin on Friday, October 17, 2008 2:03 AM
Fantastic work.  Thanks a ton for saving me a lot of time!
Comment posted by Greg on Friday, November 14, 2008 3:29 PM
Your sample is great.. but I am having a problem with the ProvidePolicyFile method.  The first time I run the console app, and try to consume the WCF service from Silverlight, it works.  The second time I get a cross domain access error .. and when I debug the console app, it reports an error that it can't open the "ClientAccessPolicy.XML" file because it is already open.  I'm getting around it by opening the file for shared-read access but that doesn't quite seem right...  any attempt to close the filestream before the method returns causes it to fail.  Any ideas?

PS There is a typo ('clientaccesspolicy' is misspelled) in the line:
FileStream filestream = File.Open(@"ClientAcessPolicy.xml", FileMode.Open);

Otherwise, fantastic..
Comment posted by David Betz on Wednesday, November 19, 2008 10:41 AM
@Nikkil
See http://www.netfxharmonics.com/2008/11/Understanding-WCF-Services-in-Silverlight-2 for JavaScript access.
Comment posted by Tobi on Tuesday, December 2, 2008 4:24 PM
Greg, i had the same problem. First run worked, the i got the error. This one works for me:

public System.ServiceModel.Channels.Message ProvidePolicyFile()
{
  XmlReader reader = XmlReader.Create(@"ClientAccessPolicy.xml");
System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);
  return result;
}
Comment posted by Harsh Bardhan on Wednesday, December 3, 2008 12:12 AM
Hi Nikhil,
You are correct that both are different technology .
But we can invoke a wcf service/asmxServices from Javascript.
You can call rest services also and invoke them using xmlHttpLObject.
You can search that online and get many article related to that.
If you still need help let me know hopefully i can create a sample for that......
Comment posted by KierenH on Friday, March 13, 2009 10:27 PM
Awesome.
Have you tried with Silverlight 2.0 RTM?
Does this work over the web? For example, Silverlight client is running on a different machine to IIS and Console/Windows service app that actually hosts the WCF service.
Comment posted by KierenH on Friday, March 13, 2009 10:29 PM
Awesome.
Have you tried with Silverlight 2.0 RTM?
Does this work over the web? For example, Silverlight client is running on a different machine to IIS and Console/Windows service app that actually hosts the WCF service.
Comment posted by Harsh Bardhan on Sunday, March 15, 2009 11:31 AM
Hi,
Yes i tried with Silverlight RTM .
Yes it will work over the web.
Comment posted by thomas on Monday, March 16, 2009 11:26 PM
great sample. Thanks, Harsh.

However, it works fine for the first 5 times when I click the "refresh" button in IE, after that, there is an exception of "The remote server returned an error: NotFound" was reported.
Comment posted by Paul Ericksen on Wednesday, April 8, 2009 10:22 PM
Thanks for writing this up. I did all of this and have it to the point where I can track (breakpoint) and watch the service respond to the request for the xml file, but then when I do the async call to my function, the service-side code never fires and I get a message about cross-domain access:

An error occurred while trying to make a request to URI 'http://localhost:8731/ConsoleApplicationHost/MediaServer/'. 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.

The InnerException is a security error.
Comment posted by Alsi on Thursday, April 23, 2009 3:51 AM
Great article. I am facing eaxactly same problem as mentioned by Paul. (An error occurred while trying to make a request to URI ...... 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.) Can someone please help?
Comment posted by Harsh Bardhan on Tuesday, April 28, 2009 1:29 AM
Hi Alsi/Paul,
Can you Run fiddler and can check at which URL your application is looking for Policy file?
Where your policy file is placed(URL)?
Comment posted by tam8421@yahoo.com on Thursday, May 7, 2009 5:11 AM
I have copy all your code to my project. But, i get error:

"An error occurred while trying to make a request to URI 'http://localhost:8731/AccessAServiceFromConsoleApplication/MyService'. 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."

I browse the link  http://localhost:8731/clientaccesspolicy.xml is get a message:
"The server encountered an error processing the request. See server logs for more details."

Can you help me resolve this problem? Thanks you very much.
Comment posted by ILang on Tuesday, June 16, 2009 12:24 PM
Very helpful article, thanks, Hash! Could you please explain the mechanism behind the call to ProvidePolicyFile method (which reads the policy file) and where the file is loaded? What makes it available to the other service on the same port? I see that the key is a certain combination of WebGet attribute, same port and app.config settings, buit how does it all tie together? Thanks!
Comment posted by ILang on Tuesday, June 16, 2009 5:13 PM
Very helpful article, thanks, Hash! Could you please explain the mechanism behind the call to ProvidePolicyFile method (which reads the policy file) and where the file is loaded? What makes it available to the other service on the same port? I see that the key is a certain combination of WebGet attribute, same port and app.config settings, buit how does it all tie together? Thanks!
Comment posted by theBoringCoder on Friday, July 24, 2009 10:06 AM
Very informative article.  I needed to build a proof of concept hosting a WCF service inside of Windows service.  The only thing I did differently is embed the ClientAccessPolicy.xml file into my WCF library, and then change the CrossDomainPolicy code to look like this:

<code>
        public System.ServiceModel.Channels.Message ProvidePolicyFile()
        {
            System.Reflection.Assembly              assembly    = System.Reflection.Assembly.GetExecutingAssembly();
            System.IO.Stream                        xmlStream   = assembly.GetManifestResourceStream("WCFServiceLibrary.ClientAccessPolicy.xml");
            System.Xml.XmlReader                    reader      = System.Xml.XmlReader.Create(xmlStream);
            System.ServiceModel.Channels.Message    result      = System.ServiceModel.Channels.Message.CreateMessage(System.ServiceModel.Channels.MessageVersion.None, "", reader);

            return result;
        }
</code>

I did that because, otherwise, the ClientAccessPolicy.xml file has to be in the windows system folder (c:\windows\system32) because that's where svchost.exe--the windows service host wrapper--is.
Comment posted by Simon on Monday, September 14, 2009 2:27 PM
For those people with the following issue:
"An error occurred while trying to make a request to URI 'http://localhost:8731/AccessAServiceFromConsoleApplication/MyService'. 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."

I browse the link  http://localhost:8731/clientaccesspolicy.xml is get a message:
"The server encountered an error processing the request. See server logs for more details."

I had the same problem and I had not correctly modified the app.config to include the following:

          <endpointBehaviors>
            <behavior name="CrossDomainServiceBehavior">
              <webHttp />
            </behavior>
          </endpointBehaviors>

Check the sample app.config in the original article for details.

Good luck!
Comment posted by Aashish Gupta on Wednesday, September 16, 2009 10:42 AM
There can be issues where you are able to run it for the first time or sometimes you will feel that its driving you crazy that could be because some other program is using the clientaccesspolicy file because you might have opened it simultanously in Firefox and IE or may be some other.
For those of you the line given in code doesn't allow shared access
FileStream filestream = File.Open(@"ClientAcessPolicy.xml", FileMode.Open);
Change this line to
FileStream filestream = File.Open(@"ClientAcessPolicy.xml", FileMode.Open,FileMode.Read,FileShare.Read);
That would resolve your error.

But anyways great article.
Comment posted by Simon on Thursday, September 17, 2009 4:15 PM
Since I was creating this in a C# COM DLL, I also had to define the service programmatically rather than in the app.config.

For those who are interested:

                // CrossDomainService definition
                m_crossDomainServiceHost = new ServiceHost(typeof(CrossDomainService));
                // Create the service end points
                WebHttpBinding bindingCrossDomainService = new WebHttpBinding();
                ServiceEndpoint endpointCrossDomainService =
                    m_crossDomainServiceHost.AddServiceEndpoint(
                        typeof(ICrossDomainService),
                        bindingCrossDomainService,
                        "http://localhost:8731/");
                WebHttpBehavior behaviourCrossDomainService = new WebHttpBehavior();
                endpointCrossDomainService.Behaviors.Add(behaviourCrossDomainService);

                // Open for business
                m_crossDomainServiceHost.Open();

Or you could still keep app.config and do:

            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE",
                @"app.config");

But then you have to ship app.config... ugly

I also placed the xml doc in a resource:

            StringReader stringStream = new StringReader(Properties.Resource.ClientAccessPolicy_xml);
            XmlReader xmlReader = XmlReader.Create(stringStream);
            System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", xmlReader);
            return result;

Enjoy!
Comment posted by Ronald on Wednesday, September 23, 2009 8:19 PM
i'm hosting the wcf service as windows service and you sample is not working for my windows service... would you suggest?
Comment posted by Shaojun Ni on Thursday, October 1, 2009 3:01 PM
For the windows service, the working directory is c:\windows\system32. So the CrossDomainService code has to change to following:
                string cmdLine = Environment.CommandLine;
                int nPos = cmdLine.LastIndexOf(@"\");
                string strPolicyFile = cmdLine.Substring(1, nPos) + @"ClientAccessPolicy.xml";
                XmlReader reader = XmlReader.Create(strPolicyFile);
                System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);

Comment posted by moudhaffar on Monday, October 5, 2009 12:15 PM
thanks for the article, i enjoy! Can you postulate an article about hosting wcf services in IIS, spetially, how we deal with the ClientAccessPolicy File.
best regards
Comment posted by Kate on Wednesday, October 21, 2009 12:09 PM
Excellent example...thanks...
I have a WCF service hosted in Windows service. I had problem with Cross-Domain....By using OpenRead instead of Open in reading the ClientAccessPolicy file, the problem has been solved:

FileStream filestream = File.OpenRead(@"ClientAcessPolicy.xml");
Comment posted by Kate on Wednesday, October 21, 2009 12:10 PM
Is it possible to post a sample how to use authentication in Silverlight 3 and WCF?

thanks
Kate
Comment posted by Sunny on Tuesday, October 27, 2009 12:41 PM
Hi host,

There is a typo in the "Step 8: Our CrossDomainService.cs or .vb will look like this. Here we are reading an Xml file and returning that." section

the "ClientAcessPolicy.xml" file name is missing a 'c'.
Comment posted by ferek on Monday, January 4, 2010 5:41 PM
It was interesting to get this clear sample. I however got a different issue where I can access the plicy but failed to get the main service. Any help please? I could access the main service from another colsole application without problem.
The error message is the obvious one "An error occurred while trying to make a request to URI 'http://localhost:8731/AccessAServiceFromConsoleApplication/MyService/'...."

Thanks!
Comment posted by Suman on Tuesday, January 26, 2010 3:49 AM
Hi Harsh,

We have a build Rest WCF services and we are accessing this Services in Silver light, but IIS were we are planing to deploy the WCF services is Shared IIS (WebFarm). And we don't have permission to deploy the CrossDomain and ClientPolicy XML file on the root directory.

Do you have any idea or suggestion for deploying the WCF services without CrossDomian or ClientPolicy XML in IIS

Thanks and regards,
Suman
Comment posted by Raghava on Thursday, February 18, 2010 7:45 PM
First...This article is very helpful to Sliver Light startars like me. Excellent!!!

Many were expressed problems with the ClientAccessPolicy.xml path. Why don't you use AppDomain.CurrentDomain.BaseDirectory to get the windows service base directory and use to get the full/absolute path of ClientAccessPolicy.xml.

The original article is using the FileStream with Open mode which causes lock on the file and subsequent requests see errors. The following code avoid that problem. This also gets service path dynamically.

   XmlReader xr = XmlReader.Create(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"ClientAccessPolicy.xml"));
   Message result = Message.CreateMessage(MessageVersion.None, "", xr);
Comment posted by Julien on Wednesday, February 24, 2010 4:49 AM
Hello,

first I would say thank you for your explanation. It helps me a lot to start my project.
Everything is working well on my own environment, but I meet some issues when I try to deploy on our Dev server.

- Web project is now hosted by IIS 6.0 on a Windows Server 2003. Silver light application is accessible from the server and an other computer.
- Console Application (Hosting WCF Service) is also installed on the same server. And Services are also available in local and from an other computer.

But when my silver light project is trying to access to WCF Services I got Exception (in the browser) saying :

Message: Unhandled Error in Silverlight Application An exception occurred during the operation, making the result invalid.  Check InnerException for exception details.   at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
   at ConsumeWCFFromConsoleApplication.ServiceReference1.PingPongCompletedEventArgs.get_Result()
   at ConsumeWCFFromConsoleApplication.MainPage.consoleClient_PingPongCompleted(Object sender, PingPongCompletedEventArgs e)
   at ConsumeWCFFromConsoleApplication.ServiceReference1.MyServiceClient.OnPingPongCompleted(Object state)
Line: 1
Char: 1
Code: 0
URI: http://localhost:2202/ConsumeWCFFromConsoleApplication.Web/ConsumeWCFFromConsoleApplicationTestPage.aspx

If anybody have an idea on which direction I search to solve this issue, that's could be great.
Starting to be crazy ... and wondering if the architecture I want to use if the right solution.

Thanks.
Comment posted by karan on Wednesday, March 10, 2010 5:34 AM
How to use Mvc in Wcf service?
Comment posted by Hitoshi on Monday, March 15, 2010 1:34 AM
Thank you very much, Harsh!!!

This helps me a lot!
Comment posted by Hitoshi on Monday, March 15, 2010 1:46 AM
Hi Tobi and Greg,
I had the same trouble right after I posted the last comment above.
The first time it worked and the second time it failed.
But it now works thanks to the revised code by Tobi.
Comment posted by Hitoshi on Monday, March 15, 2010 2:49 AM
p.s.
I also needed to copy ClientAccessPolicy.xml to \bin\Debug directory instead of \bin.
Comment posted by cristian on Monday, March 15, 2010 10:19 AM
Simon, you're the man!
Comment posted by richosting on Tuesday, March 30, 2010 2:07 AM
Great article, 5 star! i followed the steps and made little modifications, the service can be run many times without errors, but it only worked in the same machine. i wanted to try over the web, so i use 2nd PC that uses different internet provider, created a simple Silverlight 3 application, i was able to connect to the service on 1st PC (using Add Service Reference). But when i run it, it says:

An error occurred while trying to make a request to URI 'http://localhost:9001/AccessAServiceFromConsoleApplication/MyService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.

any ideas on how i can make it run over the web?

Comment posted by Venkatesh on Thursday, May 6, 2010 1:33 AM
Hi Harsh,

I think the code that host the cross domain service should be WebServiceHost and not the normal serviceHost.

Thanks and regards
Comment posted by Alistair on Saturday, May 8, 2010 10:17 AM
Fantastic post & replies. Exactly what I was looking for. I now have a windows service hosting WCF services that is Silverlight 4 friendly.
Comment posted by SilverMan on Wednesday, June 2, 2010 4:03 AM
Hi,

have you find the reason why the service don't work over the web ? (I have the same error message than you). I have try with WebServiceHost but no luck
thanks for reply
Comment posted by reena on Friday, June 18, 2010 2:30 AM
very very nice. bt yet i couldnt read this article.

Comment posted by r on Thursday, October 28, 2010 5:24 AM
Excellent article for newbies like me!I get the same error-
"An error occurred while trying to make a request to URI 'http://localhost:9001/AccessAServiceFromConsoleApplication/MyService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details."

This may be because the port number of WCF application and hosting application are different.I have tried all the solutions mentioned above but none  of them works.Can you please provide some solution Harish?
Comment posted by TheBlackKnight on Wednesday, November 10, 2010 9:49 AM
For people who are getting the "An error occurred while trying to make a request to URI 'http blah blah blah". In step 8 if directly copying the code from this site then make sure ClientAcessPolicy.xml is spelt correctly as ClientAccessPolicy.xml.  I have just fallen for this one!
Comment posted by Ernest Durelle on Monday, November 15, 2010 7:17 AM
Well done.  Simple and to the point.
Comment posted by Viral Panchal on Wednesday, November 17, 2010 12:27 AM
Hi,
thanks for this example.
when i execute silver light application i am getting error of cross domain.
i have done code as per above.

Error :
An error occurred while trying to make a request to URI 'http://localhost:8731/WCFSLConsoleApplication/MyService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.
Comment posted by Jana on Tuesday, November 23, 2010 3:07 AM
Followed exactly you have given and You saved a day for me.
Thanks you very much for the article.
Comment posted by Wcf learner on Thursday, December 9, 2010 3:21 AM
This article is the most helpful one in all web pages. I've resolved my problem (a WCF service can't be accessed in another machine) after apdating the ClientProxy xml.
Comment posted by Roberto Dalmonte on Wednesday, December 15, 2010 2:21 AM
Excellent. I replaced the console app with a WPF app and it runs without problem. Now, since Silverlight 4 supports net.tcp protocol, which is way faster than basicHttpBinding I tried adding the following modifications to make it work with net.tcp:
1) I added an endpoint to the host app.config
<endpoint address="net.tcp://localhost:4502/DataService" binding="netTcpBinding"
          bindingConfiguration="bindingConfig" name="FastDataService"
          contract="OneClick_Server.IDataService" />
2) I added a binding configuration in the bindings section of the same app.config
      <netTcpBinding>
        <binding name="bindingConfig">
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
3) I modified the ClientAccessPolicy.xml file adding one line in the grant-to section
      <grant-to>
        <resource path="/" include-subpaths="true"/>
        <socket-resource port="4502" protocol="tcp"/>
      </grant-to>
4) in the ServiceReferences.ClientConfig I added an endpoint
      <endpoint address="net.tcp://localhost:4502/DataService" binding="customBinding"
                bindingConfiguration="fastBinding" contract="DataServiceReference.IDataService"
                name="FastDataService" />
and a custombinding in the bindings section
<customBinding>
                <binding name="fastBinding">
                    <binaryMessageEncoding />
                    <tcpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
            </customBinding>

Now I get a cross-domain error. Does anyone now how to make it work with net.tcp or can spot any mistakes in my sample?
Best Regards
Comment posted by micheal on Sunday, January 16, 2011 12:34 AM
i have a small demo application to be made with silverlight and wcf. i want it to be finished in two weeks and am willing to pay a fair price. if anybody is interested please email me at "*****@*****"
Comment posted by Admin on Sunday, January 16, 2011 2:21 AM
Please do not post email id publicly. You may get spammed.
Comment posted by shilpa on Thursday, January 27, 2011 5:27 AM
I m gettin this same error pls suggest fix for same


An error occurred while trying to make a request to URI 'http://localhost:8731/AccessAServiceFromConsoleApplication/MyService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.
Comment posted by prabhakar tiwary on Friday, February 18, 2011 4:26 AM
gr8 work I like dis article, It's very useful.
Comment posted by symorium on Monday, March 21, 2011 2:02 AM
Thank you for this article. It solve my problem with crossdomain access from silverlight application.
I'm just add:
<identity>
            <dns value="localhost" />
</identity>
to basicHttpBinding endpoint(MyService).
Comment posted by Angel Calvas on Wednesday, March 23, 2011 8:55 PM
Like they mentioned Before

Replace
FileStream filestream = File.Open(@"ClientAccessPolicy.xml");

With
FileStream filestream = File.Open(@"ClientAccessPolicy.xml", FileMode.Open, FileAccess.Read,FileShare.Read);

This will solve the problem If its Shared USe

An error occurred while trying to make a request to URI 'http://localhost:8731/AccessAServiceFromConsoleApplication/MyService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.
Comment posted by Diwakar on Monday, August 1, 2011 4:04 AM
Hi, I followed exactly what is explained but i am getting the following exception:
An error occurred while trying to make a request to URI 'http://localhost:8731/ScanConsoleApplication/ScanService'. 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. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.

I am using Visual Web Developer 2010 Express Edition and Silverlight 4.0 to build the sample. Please explain what could be the possible issue.

Thanks!
Comment posted by deepak0707 on Monday, November 21, 2011 2:33 AM
http://interview-development.blogspot.com/2011/11/wcf-with-silverlight.html is good for understanding wcf with silverlight :)
Comment posted by Martin Kirk on Tuesday, November 29, 2011 2:25 AM
THAAAANKS !!!

This article was EXACTLY what i was looking for - a WCF Service which is able to declare CrossDomain accessrights by it self !
Comment posted by Hi on Wednesday, March 6, 2013 2:48 PM
Good one

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel