WCF Multiple Service Endpoints - wcf

I am hosting a WCF Service as a Windows Service.
A snapshot below.
myHost = new ServiceHost(typeof(AnalyticsService));
Uri address = new Uri("http://localhost:8080/MathServiceLibrary");
WSHttpBinding binding = new WSHttpBinding();
binding.MaxReceivedMessageSize = 2147483647;
binding.MaxBufferPoolSize = 2147483647;
//binding.Security.Mode = SecurityMode.None;
Type contract = typeof(IAnalyticsService);
myHost.AddServiceEndpoint(contract,binding,address);
As you can see I have previously been only exposing the Service locally. I would like add another ServiceEndpoint so that other machines on my network can also call the service.
I assume I would need to add something like this to the above code:
myHost = new ServiceHost(typeof(AnalyticsService));
Uri address = new Uri("http://localhost:8080/MathServiceLibrary");
Uri new address = new Uri("http://xxx.xxx.xxx:8080/MathServiceLibrary");
WSHttpBinding binding = new WSHttpBinding();
binding.MaxReceivedMessageSize = 2147483647;
binding.MaxBufferPoolSize = 2147483647;
Type contract = typeof(IAnalyticsService);
myHost.AddServiceEndpoint(contract, binding, address);
myHost.AddServiceEndpoint(contract, binding, newaddress);
Now my current service library APP config looks like:
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceLibrary.Service1Behavior"
name="ServiceLibrary.AnalyticsService">
<endpoint address="" binding="wsHttpBinding" contract="ServiceLibrary.IAnalyticsService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/ServiceLibrary/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceLibrary.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 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 -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
While my app.config in the Service Library host is
<system.serviceModel>
<services>
<service name="ServiceLibrary.AnalyticsService"
behaviorConfiguration ="MathServiceMEXBehavior">
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MathService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceMEXBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I assume I need to add another base address to the service library file with the external (non-local-host) address. I am confused about what to alter in the Service Library File.

No, you cannot add a second http based base address - you only get to choose one per protocol - one for http, one for net.tcp and so on.
What you need to do is create a second endpoint in your app.config for your service host application (the app.config from the service library will never even be used - forget about that file), and assign it a fully qualified address.
<system.serviceModel>
<services>
<service name="ServiceLibrary.AnalyticsService"
behaviorConfiguration ="MathServiceMEXBehavior">
<endpoint name="firstEndpoint"
address=""
binding="wsHttpBinding"
contract="IAnalyticsService" />
<endpoint name="secondEndpoint"
address="http://xxx.xxx.xxx:8080/MathServiceLibrary"
binding="wsHttpBinding"
contract="IAnalyticsService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MathService"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
So the firstEndpoint would use the base address and you'd be able to call it under
http://localhost:8080/MathService
while the secondEndpoint uses a specific, fully qualified URL and you'd be able to call it under
http://xxx.xxx.xxx:8080/MathServiceLibrary
However: why do you want to have a second endpoint at all?? You normally only have a second endpoint if you want to expose different protocols, e.g. you'd typically have one http, one https, one net.tcp endpoint and so on. Having two separate http endpoints with the same contract and same binding doesn't really make a lot of sense to me.....

Related

Issues while Creating an instance of the Uri class to hold the base address of the WCF service

I have created separate solutions as follows:
Solution A - that defines and implement the service contract for service R with interface IR and project name is ALib.
Solution B - host the service contract and runs it.
When I run the host application, it runs fine, but I cannot access the url with the base address provided. I updated the App.config file as instructed inside
WCF Tutorial
Lets break down what has been updated inside the App.config file.
1. <service name="ALib.R">
2. <add baseAddress = "http://localhost:8000/A/R" />
3. <endpoint address="" binding="wsHttpBinding" contract="ALib.IR">
When I type the url "http://localhost:8000/A/R" I get HTTP 400 error, but I get the page with "http://localhost:8000/A/". This is not how it is done inside the tutorial. I have enabled the metadata as well follows:
var smb = new ServiceMetadataBehavior
{
HttpGetEnabled = true
};
selfHost.Description.Behaviors.Add(smb);
Is there anything missing from what being done so far ?
Please try the following configuration.
<system.serviceModel>
<services>
<service name="Server6.MyService">
<endpoint address="" binding="wsHttpBinding" contract="Server6.IService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="Server6.IService"></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:13050/A/R"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"></serviceMetadata>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Feel free to let me know if there is anything I can help with.

Service Reference Error - netTcpBinding

I was working on WCF service with an endpoint binding of netTcpBinding, hosted in a console application.
These are the configuration settings:
<system.serviceModel>
<services>
<service name="FullTimePartTime_EmpWCFServiceAppl.EmployeeService"
behaviorConfiguration="mexBehaviour" >
<endpoint
address="EmployeeService"
binding="netTcpBinding"
contract="FullTimePartTime_EmpWCFServiceAppl.IEmployeeService">
</endpoint>
<endpoint
address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:7090/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The console application executes fine. WPF is client app which should consume the WCF service, but when I tried to add a service reference, this error occurred:
Service Reference Error
Can anyone help me to fix this issue & let me know the mistake I made?
Thanks in advance.
Always the metadata discovery is through http.So you need to have one more base address for the http which publishes the metdata via http.
<host>
<baseAddresses>
<add baseAddress="http://localhost:7091/"/>
<add baseAddress="net.tcp://localhost:7090/"/>
</baseAddresses>
</host>
First try to browse the metadata through http://localhost:7091/?wsdl. Now try to generate proxy class using the service reference address http://localhost:7091/.

WCF IMetadataExchange Error

I have created a service host with following configuration.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="MathServiceLib.MathService" behaviorConfiguration="myMathServiceBehave">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/MathService"/>
<add baseAddress="net.tcp://localhost:9002/MathService"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:9001/MathService" binding="basicHttpBinding" contract="MathServiceLib.IMathService"/>
<endpoint address ="net.tcp://localhost:9002/MathService" binding ="netTcpBinding" contract="MathServiceLib.IMathService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<!--<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myMathServiceBehave">
<!--<serviceMetadata httpGetEnabled="true"/>-->
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I don't want to use serviceMetadata httpGetEnabled="true" property instead I want to use MEX binding for proxy creation.
Now when I start my service using
svcHost = new ServiceHost(typeof(MathServiceLib.MathService));
svcHost.Open();
I get following error, please help.
The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service MathService. Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract.
Based on my experience, you need to specify
<serviceMetadata httpGetEnabled="true"/>
if you want to use
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
The following articles provide comprehensive information and examples:
http://msdn.microsoft.com/en-us/library/ms734765(v=vs.110).aspx
http://www.c-sharpcorner.com/UploadFile/81a718/wcf-service-faqs-part-2/

mexHttpBinding - Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract

I know this has been asked many times, and answered many times, but, all the provided samples that should be working don't seem to want to work for me today.
When I try to start the host, I keep getting the following error:
"The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service TraceService. Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract."
My service is being hosted in a managed windows service host as per Microsoft's example: http://msdn.microsoft.com/en-us/library/ms733069%28v=vs.90%29.aspx
And here is my nice and simple config:
<system.serviceModel>
<services>
<service name="Daff.Lae.Service.TraceService">
<endpoint address="" binding="wsHttpBinding" name="TraceService" contract="Contracts.Service.ITraceService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/TraceService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Of course, the problem becomes more interesting when there are no errors if I remove this line:
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
Any help would be very very very greatly appreciated :)
Be sure to specify a behaviorConfiguration in the service element of your configuration in order to allow either httpGet or httpsGet.
I see that you have already defined a serviceBehavior named DefaultBehavior - now all you need to do is add behaviorConfiguration="DefaultBehavior" to the service element, so that line becomes:
<service name="Daff.Lae.Service.TraceService" behaviorConfiguration="DefaultBehavior">
If you don't explicitly specify a behavior for your service, both HTTP GETs and HTTPS GETs are disallowed by default, and your metadata will not be exposed.
As you're using WS-Http you are binding to an HTTPS protocol, so you need to use the correct MEX binding;
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
and change the baseaddress to a https one.
Or (the other way around) convert your wsHttp binding to a basicHttp binding and things will start working for you.
`<services>
<service name="MyService.Service1" behaviorConfiguration="Service1" >
</services>
`
where MyService is the application name , Service1 is the default implementation class for IService1
`
<protocolMapping>
//Remove any http or https bindings provided
</protocolMapping>
`
It should help when you use WCF Application Project

Consume WCF without app.config

I need to consume a WCF service from a DLL, hence i don't have any configuration file to read bindings configurations from.
I'm having a really hard time getting it to work. In the end, as a very simple solution, I add a reference to the WCF and instantiate it like this:
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress address = new EndpointAddress("http://myhost.net/Service.svc");
ServiceReference.ServiceClient client = new ServiceReference.ServiceClient(binding, address);
var result = client.Method1();
In localhost this simply works. When trying it from another machine, i get this error:
The request for security token could not be satisfied because authentication failed.
In the host, IIS is set to "Anonymous", so I guess it should simply work.
Any help?
EDIT: Service Config File
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
<system.serviceModel>
<services>
<service name="Mai.MyPlanner.Service">
<endpoint address="" binding="wsHttpBinding" contract="Mai.MyPlanner.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://MY_SERVICE"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<connectionStrings>
<!-- PROD -->
<!-- TEST -->
</connectionStrings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
Use this code:
WSHttpBinding binding = new WSHttpBinding();
EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("localhost");
EndpointAddress address = new EndpointAddress("http://myhost.net/Service.svc", identity);
ServiceReference.ServiceClient client = new ServiceReference.ServiceClient(binding, address);
var result = client.Method1();
You will still need to pass Dns identity value and address into your method calling this code. Also this type of configuration will work only in intranet (same windows domain) because it by defult uses message security and Windows authentication.
Use basic http binding instead, if you do not require security.
What if you'd have a ServiceHost that would take a ServiceEndpoint such as below:
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICalculator), binding, "CalculatorService");
How would you still programmatically specify App.config elements such as:
<services>
<service name="GettingStartedLib.CalculatorService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8000/GettingStarted/CalculatorService" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="wsHttpBinding" contract="GettingStartedLib.ICalculator">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>