WCF / Csla Hell - wcf

I'm trying to build a proof of concept Csla 3.7/Silverlight 3 app and have been working my way through Rocky's tutorials. It's a really simple one form/one business object data editing app and everything is just peachy right up until the point where I try to get the Wcf configured so that the Silverlight app can talk to the Data Portal.
The error I'm getting is:
CommunicationException was unhandled by user code
An error occurred while trying to make a request to URI 'http://localhost:1406/WcfPortal.svc'.
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'm totally mystified by this as I'm a bit of a n00b to Silverlight & WCF. My setup is pretty straight forward for a Csla Silverlight app. I have 4 projects:
CslaSilverlight : Silverlight Project
CslaSilverlight.Client : Silverlight Class Library
CslaSilverlight.Server : .NET Class Library
CslaSilverlight.Web : ASPNET Project to host the SL app
Everything is running locally on my laptop under Cassini. I want the DataPortal to run outside of Silverlight so that I can access SQL Server. I think that the problem may be with my Wcf Config in the Silverlight application which is specified in a ServiceReferences.ClientConfig file:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IWcfPortal" maxBufferSize="65536"
maxReceivedMessageSize="65536" receiveTimeout="10" sendTimeout="10">
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1406/WcfPortal.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IWcfPortal"
contract="Csla.WcfPortal.IWcfPortal" name="BasicHttpBinding_IWcfPortal" />
</client>
</system.serviceModel>
</configuration>
I'm wondering if the port number important, when I change it I get a different error. I'm also wondering if the format of the endpoint address correct.
Not sure if it's important, but my serviceModel settings from the ASPNet web.config are:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WcfPortalBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="WcfPortalBehavior" name="Csla.Server.Hosts.Silverlight.WcfPortal">
<endpoint address="" binding="basicHttpBinding" contract="Csla.Server.Hosts.Silverlight.IWcfPortal">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>

If I am thinking it right, then the error may be telling you the entirely correct thing, you are missing a cross domain policy. The silverlight app is accessing the WCF service from a remote location and needs the authorisation to accept the request.
This occured for me in dev when the project was in three parts, the SL App, the WCF web service and the website. The web site and WCF service are run independantly, although they were a part of the same solution. As such Cassini is run twice and you are crossing a boundary.
I have a clientaccesspolicy.xml file along with the web service in development that has the following:
<?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>
The file is a allowing anyone and everything, you would refine it for production, but in dev it was the easiest way. Google wcf client access policy / wcf cross domain policy - it is a common issue.

Related

"There was no endpoint listening at" issue with a IIS Hosted WCF Service consuming another web service

I have created a WCF service which is hosted in IIS and that tries to call another web service (3rd party) to return some data. When trying to connect the service fails with the following error:
There was no endpoint listening at https://xxx (3rd party ws) that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
And this is while, my service is up (i know from my echo method) and it works successfully if it is self hosted.
I have the whole and sections copied to the model of web.config exactly as it is for the self hosting test but something still is missing.
I have been through other similar problems reported but mine is little bit specific in that the service is kind-of hosting another one and that one is causing the issue.
I can try to exlain better with a real example:
There is a simple web service here: http://www.dneonline.com/calculator.asmx which I want to wrap inside our library and provide access to via an IIS hosted WCF.
So, a class library is created (Calculator project) to with one method, add to take two int arguments and use them to call the web service add method. The webservice is referenced as a Service Reference inside the library and is being addressed inside from within the config library app.config file like below:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="CalculatorSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://www.dneonline.com/calculator.asmx"
binding="basicHttpBinding" bindingConfiguration="CalculatorSoap"
contract="Service.CalculatorSoap" name="CalculatorSoap" />
</client>
</system.serviceModel>
</configuration>
Then there is a WCF class library (CalcService project) which uses the first class library to enable http endpoints. Again, the app.config file includes endpoints both as for the service itself and as a client of the class library. The app.config file looks almost like this:
<configuration>
<system.serviceModel>
<services>
<service name="CalcService.Calc">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/CalcService/Calc/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="CalcService.ICalc">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<!-- Client endpoint, i.e. to be able to use the calculator.asmx service addressed in the class library -->
<client>
<endpoint address="http://www.dneonline.com/calculator.asmx"
binding="basicHttpBinding"
contract="Service.CalculatorSoap" name="CalculatorSoap" />
</client>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I am able to test the whole thing via a console application that makes a call to the WCF service and receives an answer. The console application config file has only one client endpoint to the WCF like below:
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/CalcService/Calc/"
binding="basicHttpBinding" contract="Calculator.ICalc" name="BasicHttpBinding_ICalc" />
</client>
</system.serviceModel>
</configuration>
My question is now how I can host the WCF service inside IIS? I have tried different ways but neither one worked. My current IIS project (which doen't work) looks like this:
1-Has project references to both prevoius projects (Class Library and WCF Service) so two dll files are being added to the references:
CalcService.dll
Calculator.dll
2-Has a CalcService.svc file which creates a ServiceHost toward the CalcService:
<%# ServiceHost Language="C#" Debug="true" Service="CalcService.Calc"%>
3-Has a web.config with cliend endpoint to calculator.asmx:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="CalculatorSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://www.dneonline.com/calculator.asmx"
binding="basicHttpBinding" bindingConfiguration="CalculatorSoap"
contract="Service.CalculatorSoap" name="CalculatorSoap" />
</client>
<!-- some other settings -->
</system.serviceModel>
Now, when tested with a simple client to make a call to the calculator add method it fails with the following error:
There was no endpoint listening at http://www.dneonline.com/calculator.asmx that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
I don't know which message the endpoint is expecting, I could just assumed it has to be Service.CalculatorSoap as it worked before from the console application.
On the other hand, what confuses me is that a self hosted WCF also works (via http://localhost:8733/Design_Time_Addresses/CalcService/Calc/ from the config file in the WCF class library project).
I don't know what is missing here, is it something from the IIS configuration or permissions?
Or someting else like the windows firewall setting like explained in this post:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/bec3ab7a-310e-415f-b538-6d5681e5e53c/there-was-no-endpoint-listening-at?forum=wcf
Just note that since I am using a company computer, I'm not able to shut down the firewall. I can just turn on/off some of the rules.
I hope it is clear now what we are after.
We tested the solution on a cloud based machine and it worked fine. In the end it looked to be some firewall rules blocking the IIS outgoing calls and nothing was wrong in the configuration files or in the code.

How to Resolve EndpointNotFound exception in WCF

I have been trying to resolve a problem that I am having with a WCF service hosted on our cloud platform. Service is written targeting .NET 4.0. I can access the service using both wsHttpBinding and basicHttpBinding over just plain http. However, when I try and access the service over a https end point it consistently gives me an endpoint not found exception which is odd because on the client I add a service reference pointing at the https end point and this should be sufficient to build a compatible proxy?
The web site has a SSL certificate setup which is valid, and the site hosting the service has a binding in IIS that uses this certificate. I can browse to the https URL from within the IIS snap-in and it finds the service with no problems, and I can use the same url from my desktop and get the normal "you have created a service page". IIS has anonymous authentication enabled only.
Here is where I get a bit hazy on what I have to do in terms of the WCF configuration.
In the server web.config I have security mode of Transport and
client credentials of None (Think I need this because of the
anonymous authentication on the host service)
Also in the server web.config I have set up mex end points for each
of the server's end points that are defined.
Is there anything else I need to do here?
On the client side
I have created a basic console app, and create a service
reference pointing at the https url and this is found
In the code I instantiate the proxy and call a method that invokes
the service.
When I run the code I get the end point not found exception.
I have created a really basic ASP.NET web site on my local IIS that hosts a really simple service. I have added a self-signed certificate and in the mmc snap-in I have imported this as a trusted certificate. I have set up a wsHttp end point for both secure and non-secure and when I create a simple client that references the service I get the same problem when using a https end point.So I can replicate the problem I am seeing in the live environment.
The event viewer doesn't shed any light on anything untoward happening.On my various searches I found references to re-registering asp.net and the WCF runtime components. Tried all this to no avail. Getting really stuck. I've included the config from my local asp.net web site, and the client config so people can scan what I have. Any suggestions on what else I could try would be great. I'm hoping I have overlooked something obvious that another pair of eyes with more experience with WCF can spot.
Thanks in advance.
Server config:
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="500" />
</diagnostics>
<services>
<service name="NorthwindServices.ProductService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/NorthwindServices/ProductService/" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="NorthwindServices.IProducts">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="wsHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Secure">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic">
</transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</
==================================================================================
Client config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IProducts">
<security mode="Transport"></security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/Northwind.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IProducts" contract="ProductProxy.IProducts"
name="WSHttpBinding_IProducts">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
BindingConfiguration is optional since an endpoint is primarily composed of address, binding and contract. If no wsHttpBinding is defined under bindings, the default configuration will be used; if there's one under wsHttpBinding without name or with empty name, the binding configuration will be used if the endpoint does not declare a named one. And you may have multiple named binding configuration under wsHttpBinding, and each endpoint may pick one accordingly. The problems so far according to your config files listed has nothing to do with bindingConfiguration as they all look fine. However, the baseAddress in service side and the client endpoint address do not seem to match, and I presume you are using svc files for service activation. Then you need to make sure the svc files are located in the right place through proper routing. Alternatively you may use config activation without using svc files.

Silverlight WCF Service only working on local host

Apologies for the long post but I want to include as much information as possible. So I've been struggling for days now to get my WCF service to work correctly with my silverlight app. I had originally deployed it and everything was running smoothly.
However After i made an update to one of the methods it has not worked since. I use SVN to store my work and even going back to previous versions of the project and redploying it has not helped. Please can someone assist me :(
If I run my silverlight application through VS2012 it works correctly all calls to the service work as required and retrieve the correct information. However if i trigger the same calls once the silverlight app is deployed I receive 1 of the following errors:
An exception occurred during the operation, making the result invalid. Check InnerException for exception details.
at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
at OrionDashboard.OrionWebService.GetTestDataCompletedEventArgs.get_Result()
at OrionDashboard.MonthlyOverview.OrionWebService_GetTestDataCompleted(Object sender, GetTestDataCompletedEventArgs e)
at OrionDashboard.OrionWebService.OrionWebServiceClient.OnGetTestDataCompleted(Object state)
Or
[Async_ExceptionOccurred] Arguments: Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.dll&Key=Async_ExceptionOccurred at
With the rest of the error corresponding to the onComplete event error of the other error message.
Again this only happens when its deployed to the IIS on the server, And it only started happening after i made the update an redeployed
I've used both WCF Storm and WCF Test Client that was included with VS2012 to test the deployed service over the network and everything is being returned without any issues for all the contracts.
Here is the ServiceReferences.ClinetConfig:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_OrionWebService">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:53493/OrionWebService.svc"
binding="customBinding"
bindingConfiguration="CustomBinding_OrionWebService"
contract="OrionWebService.OrionWebService"
name="CustomBinding_OrionWebService" />
</client>
</system.serviceModel>
I have made no changes to this at all from what was auto generated when i referenced the service project. I thought it may have been this line: "http://localhost:53493/OrionWebService.svc"
because in fiddler i receive the following errors on the crossdomain.xml and the clientaccesspolicy.xml
[Fiddler] The socket connection to localhost failed.
ErrorCode: 10061.
No connection could be made because the target machine actively refused it [::1]:53493
however when i changed the xap to a zip file and modified the ServiceReference.ClientConfig to point to the same service address as would work if you wanted to check your service e.g. "http://ServerName/OrionDashboard/OrionWebService.svc" I still get the same error from silverlight and then get a 404 error from the two files.
Here is the web.config:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true"
targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="OrionDashboard.Web.OrionWebService.customBinding0">
<binaryMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="OrionDashboard.Web.OrionWebService">
<endpoint address=""
binding="customBinding"
bindingConfiguration="OrionDashboard.Web.OrionWebService.customBinding0"
contract="OrionDashboard.Web.OrionWebService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
As with the ServiceReference, the web.config too was left alone because I dont really understand what most of it means. But I left it as is when I first deployed the silverlight app and as mentioned it worked fine then.
I don't believe its a DB issue since it runs locally without any issues and the service responds with the correct data from the deployed service as well.
The service seems to be working fine, no issues reported from either the WCF Test Client or WCF Storm app
In VS2012 when publishing the wcf service it doesn't separate the service from the client and it doesn't create the crossdomain.xml or clientaccesspolicy.xml so I manually added those after publishing it. Not sure if that could possibly be the cause?
I'm completely lost and every work around I've found so far has not worked for me. Please can someone at least point me in the right direction?

WCF service calls works properly in Intranet, but not in internet

I've been working with silverlight application for over a month now, and have stumbled upon a weird issue.
I have a WCF service running in IIS, accessible from the URL :
https://xyztestname.com/service1.svc
I am able to consume this in visual studio and when deployed from visual studio, am able to get proper call backs from WCF service and everything works fine.
When i deploy the package files in to the same folder as the Service1.svc in IIS, the WCF service is not hitting properly.
Please help me resolve this issue :(! Here is my web.config file.
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="InformationService.Service1">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpEndpointBinding"
name="BasicHttpEndpoint" contract="InformationService.IService1">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
I dont know where i am going wrong. But the same Virtual folder when accessed through intranet works fine, but doesn't work when accessed through internet :( Please help.
Edit:
After checking into the client config, i found out that Visual studio automatically resolved the URL into an intranet URL. When i changed back to the internet URL, i am getting an exception thrown.
n error occurred while trying to make a request to URI 'https://xyztestname.com/Service1.svc'. 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.
However, I have copied both the crossdomain and clientaccesspolicy files into the root of the application in IIS. :( Please help.
You have to deploy your application to the specific ip and port to be able to use it in internet.
I think you can.
To do this you need to edit applicationhost.config file manually (edit bindingInformation '::')
To start iisexpress, you need administrator privileges
1 – Bind your application to your public IP address
Normally when you run an application in IIS Express, it’s only accessible on http://localhost:[someport]. In order to access it from another machine, it needs to be bound to your public IP address as well. Open D:\Users[YourName]\Documents\IISExpress\config\applicationhost.config and find your site. You will find something like this:
<site name="YOUR PROJECT NAME HERE" id="2">
<application path="/">
<virtualDirectory path="/" physicalPath="YOUR PHYSICAL PATH HERE"
<binding protocol="http" bindingInformation="*:58938:localhost" />
</bindings>
</site>
In , add another row:
<binding protocol="http" bindingInformation="*:58938:192.168.1.42" />
(But with your IP, and port number, of course)
2 - Allow incoming connections
If you’re running Windows 7, pretty much all incoming connections are locked down, so you need to specifically allow incoming connections to your application. First, start an administrative command prompt. Second, run these commands, replacing 192.168.1.42:58938 with whatever IP and port you are using:
netsh http add urlacl url=http://192.168.1.42:58938/ user=everyone
This just tells http.sys that it’s ok to talk to this url.
netsh advfirewall firewall add rule name="IISExpressWeb" dir=in protocol=tcp localport=58938 profile=private remoteip=localsubnet action=allow
This adds a rule in the Windows Firewall, allowing incoming connections to port 58938 for computers on your local subnet.
And there you go, you can now press Ctrl-F5 in Visual Studio, and browse you site from another computer!

WCF 4 Routing Multicast Configuration Frustration

I have been using stackoverflow.com as a resource as a professional programmer for years now. I would say 8 out of 10 times when I search for something on google, I get pointed to a question and answer here, and I am always relieved when that happens, because I know I am about to find the information I need.
I have been pulling my hair out trying to figure (what I think to be) a simple problem out, concerning setting up a routing service using WCF technology. I have browsed through the questions with similar titles here, and I have consulted a great many resources (both actual books on the subject, as well as websites) trying to figure this out, to no avail.
In a nutshell, I want to setup a system with the following layout:
{client}<-basicHTTP->{portal/router}<-fullWCF-WS*->{end-point-services1..n}
client: gets service reference to portal, able to call functions at end-point service
portal/router: gets requests from client, and sends them on to end-point services in a multi-cast setup
end-point-services1..n: gets request from client, routed through portal, processes request to search for things, and either responds, or logs data in a database to be checked later
I am, 100%, able to get a routing service up and running. The most successful models I have been able to follow, were outlined in the "What's new in WCF4: exercises 8 & 9, content bridging & routing" (msdn.microsoft.com/en-us/gg465212) and "Hello World with the Routing Service" (msdn.microsoft.com/en-us/library/dd795218.aspx) But I have used bits and pieces from all of the sources I have consulted (listed below).
Basically, what is frustrating me, is that I want a client (a 3rd party) to be able to just add a web service reference to the portal service (or, worst case scenario, use the svcutil.exe method), and be done with setup on their part. With that reference, they will have references to all the functions/methods they would want to call in all scenarios. The models I have looked at that do this require 2 references, one to the actual service, and one to the router, and then force the client to specifically call the router in their setup. None of my other attempts to make this particular setup work, have worked.
Your help with this would be greatly appreciated.
Here is a simplified version of my working model that almost is doing what I want:
(note, all services are being hosted in IIS)
PORTAL SERVICE (and IIS Host)
Portal.svc:
<%# ServiceHost Service="System.ServiceModel.Routing.RoutingService, System.ServiceModel.Routing, version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
Web.config:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
...
</bindings>
<client>
<endpoint address="http://searcher1/Searcher.svc/general" binding="basicHttpBinding" contract="*" name="regularSearchServiceEndpoint" />
<endpoint address="http://searcher2/Searcher.svc/general" binding="basicHttpBinding" contract="*" name="regularSearchServiceEndpoint2" />
</client>
<behaviors>
...
</behaviors>
<routing>
<filters>
<filter name="MatchAllFilter" filterType="MatchAll" />
</filters>
<filterTables>
<filterTable name="filterTable1">
<add filterName="MatchAllFilter" endpointName="regularSearchServiceEndpoint" backupList="backupList1" priority="0"/>
</filterTable>
</filterTables>
<backupLists>
<backupList name="backupList1">
<add endpointName="regularSearchServiceEndpoint2"/>
</backupList>
</backupLists>
</routing>
<services>
<service behaviorConfiguration="routingConfiguration" name="System.ServiceModel.Routing.RoutingService">
<endpoint address="general" binding="basicHttpBinding" name="routerEndpoint1" contract="System.ServiceModel.Routing.IRequestReplyRouter" />
</service>
</services>
</system.serviceModel>
</configuration>
SEARCH SERVICE
ISearch.cs:
namespace SearchService
{
[ServiceContract]
public interface ISearch
{
[OperationContract]
string Ping();
[OperationContract]
string searchByInput(string input);
}
}
App.config:
<configuration>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<bindings>
<basicHttpBinding>
...
</basicHttpBinding>
<customBinding>
...
</customBinding>
</bindings>
<client>
...
</client>
<services>
<service name="SearchService.Search">
<endpoint address="general" binding="basicHttpBinding" contract="SearchService.ISearch" name="SearchService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/SearchService/Service1/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
SEARCH SERVICE HOST
Search.svc:
<%# ServiceHost Service="SearchService.Search" %>
Web.config:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<!--copied over from SearchService.App.config-->
</basicHttpBinding>
<customBinding>
<!--copied over from SearchService.App.config-->
</customBinding>
</bindings>
<client>
<!--copied over from SearchService.App.config-->
</client>
<services>
...
</services>
<behaviors>
...
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
CLIENT (where it all goes wrong)
Only way I have been able to get it to do what I want, is to add a web service reference to the searcher service (named "remotehost"), and then manually add client endpoints to the app.config file for the router, and force the client code to use that, INSTEAD of the direct link it already has to the searcher
Main.cs:
namespace Client
{
public partial class Main : Form
{
remotehost.SearchClient proxy;
public Main()
{
InitializeComponent();
proxy = new remotehost.SearchClient("RouterService");//("BasicHttpBinding_ISearch")
}
private void button1_Click(object sender,EventArgs e)
{
string response = string.Empty;
//uses method exposed by the SearchService service
response = proxy.Ping();
MessageBox.Show("Response from remote service:\n" + response
"Ping Response",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}
App.config:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
...
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://searcher1/Searcher.svc/general" binding="basicHttpBinding" bindingConfiguration="SearchService" contract="remotehost.ISearch" name="SearchService" />
<!--I manually added this-->
<endpoint address="http://portal/Portal.svc/general" binding="basicHttpBinding" contract="remotehost.ISearch" name="RouterService" />
</client>
</system.serviceModel>
</configuration>
I want to emphasize, this all WORKS, but it doesn't work the WAY I want it to. I am fairly certain I can push/pull/cajole this into the elegant setup I am envisioning, but I can't seem to find a resource or guide that will walk me through it for the first time.
Help?
Sources I have consulted, before coming here:
Learning WCF: A Hands-on Guide, by Bustamante, Michele Leroux {978-0-5961-0162-6} (read cover to cover, and did all exercises)
Windows Communication Foundation 4: Step By Step {978-0-7356-4556-1} (focused on chapter 14: Discovering Services and Routing Messages)
msdn.microsoft.com/en-us/library/ms734712.aspx {WCF: Getting Started Tutorial}
msdn.microsoft.com/en-us/gg465212 {what's new in WCF4: exercises 8 & 9, content bridging & routing}
codeproject.com/Articles/146835/How-to-create-scalable-services-with-WCF-4-0-Route {How to create scalable services with WCF 4.0 Router and Discovery services}
msdn.microsoft.com/en-us/library/dd795218.aspx {Hello World with the Routing Service}
msdn.microsoft.com/en-us/library/ee517421.aspx {routing}
msdn.microsoft.com/en-us/library/ee517423.aspx {routing service overview}
msdn.microsoft.com/en-us/library/ee517418.aspx {routine service features}
msdn.microsoft.com/en-us/library/ee517422.aspx {routing intro}
msdn.microsoft.com/en-us/library/ee517420.aspx {routing contracts}
msdn.microsoft.com/en-us/library/bb332338.aspx {wcf routing}
msdn.microsoft.com/en-us/library/ms730158.aspx {more wcf routing}
msdn.microsoft.com/en-us/library/ee354381.aspx {more wcf routing}
dandcohen.wordpress.com/2010/03/02/wcf-4-routing-service-multicast-sample/ {WCF 4 Routing Service Multicast sample}
UPDATE: 2012-04-28:
I figured out a way to do what I wanted. It still isn't as elegant as I wanted, but it get the job done and has allowed me to move forward.
Basically, take the interface from the main service, and implement it in a new service, call it router or portal, or whatever. In the new router/portal service, add a new service reference to the main service.
Now, both services are using the same interface, and have the same signatures for all their methods, so you can then just give the portal/router service wsdl to the 3rd party client, and only allow your portal/router service to communicate with the main service.
Additionally, if you have more than one main service, you can use the portal/router service to decide which of the main services to send requests to, using multiple service references to them, and proxies to send the jobs onward. It works really well.
It is basically a manual front-end routing service, but the beauty is, the detailed work can be done in the main services on a threading model, while the gatekeeping work can be done at the portal/router, so only actual requests are sent to the main services, allowing them to only do work, and the portal services to decide how or if they get that work. The next step I want to add it automatic discovery of new services, but for now, manual configuration is working fine.
I can post the source code for what I came up with, if anyone wants to see it and requests it.
The fundamental problem is that the router knows nothing about the service contract that the service is using - it uses a universal contract (one which uses the Message type). Therefore, there is no way for the router to auto-generate the metadata for the client.
What you will need to do is provide the metadata yourself, maybe as a static WSDL document, with the correct addresses in it and point clients to this