Consume WCF without app.config - wcf

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>

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.

Role of baseAddress while configurting WCF Service EndPoint

I have created simple WCF service and configured its endpoint as bellow.
<services>
<service name="AsynchWCFService.MathOperation">
<endpoint address="MathsOperation" binding="wsHttpBinding" contract="AsynchWCFService.IMathOperation">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/OperationService/" />
</baseAddresses>
</host>
</service>
</services>
I have hosted this WCF service in a stand alone exe. I am expecting that my service will be accessible at below address.
http://localhost:8080/OperationService/MathsOperation/
But service is accessible at http://localhost:8080/OperationService/
I want to access service using http://localhost:8080/OperationService/MathsOperation/ link. Can any one help me?
I don't think your service is available at http://localhost:8080/OperationService. What you see there is just a HTML page created by WCF which describes available mex endpoints or path to WSDL.
These mex endpoints describe the ABC of your WCF service where A = address => http://localhost:8080/OperationService/MathsOperation/. Potential clients know about your service url by querying the mex endpoint.
By default, this HTML page will show up at your base address. However, you can disable this page or set it to appear at some different url by using serviceDebug behavior.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug httpHelpPageUrl="http://localhost:8080/OperationService/myhelppage"
/> <!-- use httpHelpPageEnabled="false" to disable the page -->
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Unfortunately, I don't think you can set httpHelpPageUrl to same address as your service endpoint.

Multiple Classes Implementing Same Service Contract

I have created a WCF service in which i have one service contract and multiple services classes implementing the same contract.
Could you please tell me what to edit in the app.config and how to host this service in console app.
I have one service contract and i implemented this contract in three *.cs files in wcf.
Thanks.
here is the App.config that i have written
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 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>
<services>
<service name="ProductService.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8732/Design_Time_Addresses/ProductService/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="wsHttpBinding" contract="ProductService.IService1">
<!--
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>
<service name="ProductService.RegistrationService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7777/Design_Time_Addresses/ProductService/RegistrationService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ProductService.IService1">
<identity>
<dns value ="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<service name="ProductService.ProductService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/Design_Time_Addresses/ProductService/ProductService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ProductService.IService1">
<identity>
<dns value ="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<service name="ProductService.CatogeryService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/Design_Time_Addresses/ProductService/CatogeryService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ProductService.IService1">
<identity>
<dns value ="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
</configuration>
I imagine you have defined several service operations on the service contract? What you are trying to do is not possible, nor is it desirable.
Because a logical service is associated with exactly one service contract, you cannot add more than one service for the same contract.
You can add multiple service endpoints per service contract, but not on a per operation basis. You may want to do this to offer your service across two or more different transports, for example, HTTP and HTTPS.
You can consume all the operations from a single service (you have 4 services defined, so just get rid of the last three), but I don't think that is what you want to do.
To host each service operation on a separate service endpoint, you will needs to break up your service contract into multiple contracts.
This is more desirable as it reduces coupling between your endpoints and makes it much easier to understand what is going on.

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

WCF Multiple Service Endpoints

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.....