I have a C# WCF Service Library that's running properly locally. A client running locally was able to see the service and consume it.
However, when I tried hosting the service in a WebRole and deploying it on Azure, the client was never able to connect to it successfully the same way it did locally! The way I did it was as follows:
// The WCF Service library is in namespace: Root.Library
Uri url = new Uri("http://xxx.cloudapp.net:8099/DealerService"); // tried also without "DealerService" but still didn't work
ServiceHost host = new ServiceHost(typeof(Root.Library.DealerService), url));
host.AddServiceEndpoint(typeof(Root.Library.IDealerService), new WSHttpBinding(), "DealerService");
ServiceMetadataBehavior dealerMetaBehavior = new ServiceMetadataBehavior();
dealerMetaBehavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(dealerMetaBehavior);
host.Open();
And inside Root.Library, the app.config:
<service name="Root.Library.DealerService">
<endpoint address="" binding="wsHttpBinding" name="dealer" contract="Root.Library.IDealerService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://xxx.cloudapp.net:8099/" />
</baseAddresses>
</host>
</service>
I also added an Endpoint to the WebRole config (Type:Input, Protocol:http, PublicPort:8099)
Can someone tell me what the problem might be??? this is really confusing me!
Thanks a lot!
You should just be able to change the port based on the csdef file
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="8888" />
</Endpoints>
Saqib Ullah has a post on geekswithblogs that shows more information: http://geekswithblogs.net/technetbytes/archive/2011/04/25/145035.aspx
Related
Have above 5 WCF projects. In which 4 has to be hosted as windows service and 1 in IIS. All in the same machine.
For each of the 4 WCF projects, I require 4 Windows service projects to host separately. To minimize the number of projects to be maintained, I am thinking of one single windows service to install all the 4 WCF projects for easy maintainability. Anyway apart from OnStart and OnStop I call the wcf and no other logics are there.
The challenges I see are, each Windows service requires the same app config file as used in WCF projects. If I would do this dynamically by getting the service name from app settings, How will I load the app.config file of different wcf projects to host as windows service during run time.
Is this feasible ? If so how can i achieve this ?
Yes, it's possible, you just need to configure each one endpoint in your config file. How to do that:
Windows Service WCF hoster is ServiceHost class, so you need to create 4 hosts for every contract.
var serviceHost = new ServiceHost(typeof(CommunicationManagement));
serviceHost.Open()
Now you can configure every your service endpoint in services section:
<system.serviceModel>
<services>
<service name="Communication.Service.CommunicationManagement">
<endpoint
binding="netTcpBinding"
bindingConfiguration="myBinding"
contract="Communication.Service.ICommunicationManagement"
name="CommunicationManagement">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="MEX" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/Communication/Service/CommunicationManagement" />
</baseAddresses>
</host>
</service>
<service bname="Communication.Service.Managers.PhoneAdatpersManager">
<endpoint
binding="netTcpBinding"
bindingConfiguration="myBinding"
contract="Communication.IPhoneAdministration"
name="PhoneAdministration">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="MEX" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/Communication/Service/PhoneAdministration" />
</baseAddresses>
</host>
</service>
</services>
<system.serviceModel>
Above you can see PhoneAdatpersManager and CommunicationManagement services, they hosting in a single Windows Service and works together on 8000 port (but you can use different ports).
Using the example from github, setting up a simple wcf service hosted in a windows service works fine. However, when I add another servicecontract implementation, I'm not able to host this under the same baseAddress, i.e from app.config:
<service name="ContractService" behaviorConfiguration="WebServicesBehavior">
<host>
<baseAddresses >
<add baseAddress="baseUri"/>
</baseAddresses>
</host>
<endpoint address="addr1" binding="wsHttpBinding" contract="IContract1"/>
<endpoint address="addr2" binding="wsHttpBinding" contract="IContract2"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
I'm able to host 2 services, using this example, however I would like to achieve to have multiple service contracts hosted within the same baseAddress and possible multiple endpoints, but my search for solutions to this have left me stranded.
This setup works:
<services>
<service name="ContractService1" behaviorConfiguration="WebServicesBehavior">
<host>
<baseAddresses >
<add baseAddress="http://localhost:8082/Services/"/>
</baseAddresses>
</host>
<endpoint address="addr1" binding="wsHttpBinding" contract="IContract1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<service name="ContractService2" behaviorConfiguration="WebServicesBehavior">
<host>
<baseAddresses >
<add baseAddress="http://localhost:8083/Services/"/>
</baseAddresses>
</host>
<endpoint address="addr2" binding="wsHttpBinding" contract="IContract2"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
The wireup using ninject is the same as in the github example.
Is there a way to achieve multiple endpoint using selfhost wcf with ninject?
You can have multiple services on the same port by specifying different baseAddresses for the same port.
Append the address from the endpoint definition to the base address for each of the services like so:
<add baseAddress="http://localhost:8083/Services/addr1"/>
<endpoint address="" binding="wsHttpBinding" contract="IContract1"/>
I have two WCF services in two separate DLL files. I want to host those in a single self-hosted project (console host).
I am trying to do this with following code, but I am getting this exception:
The type initializer for
'System.ServiceModel.Diagnostics.TraceUtility' threw an exception.
C# code:
public static void Main(string[] args)
{
new Program().inital();
}
private void inital()
{
ServiceHost myService = new ServiceHost(typeof(ClientNotificationService));
ServiceHost myService2 = new ServiceHost(typeof(ServerNotificationService));
try
{
myService.Open();
myService2.Open();
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
}
In App.config:
<system.serviceModel>
<services>
<service name="ClientNotification.ClientNotificationService">
<endpoint address="net.tcp://localhost:7081/CVClientNotificationService"
binding="netTcpBinding" contract="ClientNotification.IClientNotification">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/ClientNotification/ClientNotificationService/" />
</baseAddresses>
</host>
</service>
</services>
<services>
<service name="ServerNotification.ServerNotificationService">
<endpoint address="net.pipe://localhost/ServerNotificationService" binding="netNamedPipeBinding"
contract="ServerNotification.IServerNotification">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/ServerNotification/ServerNotificationService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
The reason for this error
The type initializer for 'System.ServiceModel.Diagnostics.TraceUtility' threw an exception.
is triggered when the TraceUtility tries to initialize its Event Tracing in an internal method called SetEtwProviderId().
Inspection of the inner exception shows:
Configuration system failed to initialize
and its inner exception shows:
Sections must only appear once per config file.
So it is not your code but your config file that is wrong.
I can see where the confusion on this might start. When you add an Wcf Library project to the solution you'll find this in its app.config:
<!-- 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="WcfServiceLibrary2.Service1">
<!-- rest omitted for brevity -->
So the instruction is to add that config to the app.config of your hosting applicaton, but is isn't very explicit about what exactly to copy.
You need to end-up with an app.config that is valid. You copied the <services> elements to the app.config of the application host. Now you have 2 <services> elements which is an invalid config section. Instead copy the child elements of <services> to the single <services> element in the app.config.
So to be clear:
<!-- 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>
<!-- COPY FROM HERE ... -->
<service name="WcfServiceLibrary2.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary2/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary2.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>
<!--
.... TO HERE to the app.config of your application hosts config file
-->
</services>
Assuming you already have a basic system.serviceModel config present.
If Visual Studio isn't complaining about your config file you can always start the WCF Service Configuration Editor (under the Tools menu in VS or in the context menu of the config file) to inspect the WCF config. If it is broken it will bark at you.
I have a windows service on my laptop, which hosts a WCF service. I would like to use these service on my ASP.NET website, which is on external ASP.NET server.
Could you help me, how to do this?
Is it necessary a specific laptop configuration for that? What should I configure?
And binding, what type will adequate? .. Right now, I've got:
<service behaviorConfiguration="WcfServices.InfoBehavior" name="MyProgram.WcfServices.Info.Info">
<endpoint address="" binding="wsHttpBinding" contract="MyProgram.WcfServices.Info.IInfo">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Info/" />
</baseAddresses>
</host>
</service>
UPDATE:
Right now, my client app is still on my laptop (it is not publish yet).. This is my client code:
<client>
<endpoint address="http://localhost:8732/Info/" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IInfo" contract="ServiceInfo.IInfo"
name="WSHttpBinding_IInfo">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
I don't know, what binding use.. what port, what settings should be changed on my laptop?
Unless your laptop has its own fixed IP address exposed externally (most unlikely) I think you will find it hard to do this directly.
You might consider using Azure Service Bus to broker message exchanges: I believe this is one way to solve the problem of accessing a service hosted on a non-constant IP address or behind a firewall/NAT.
Or you could consider changing your design to turn things the other way around. That is, when it is connected and running, your laptop service connects to a service hosted on the ASP.NET box, over a duplex binding, with your current service contract as the callback contract.
If you have a WCF service running on your laptop hosted via ServiceHost you'll need to duplicate that configuration in your ASP.NET web.config file, as well as add a "service.svc" file which is referenced to the Interface of your service.
You should change localhost with real external facing IP address of your laptop and it could work if your router at home has no firewall. Change it in both client and server endpoint address.
This is the configuration file while hosting the service, here i hosted service using ip 127.0.0.1:36345, here service is not accessible using netTcpBinding
when i hosted the using the exact ip of server (192.168.1.47:36345) it works..
what could be possible reason and solution?
<services>
<service behaviorConfiguration="metadataSupport" name="WCFSvc.WCFService">
<endpoint binding="wsDualHttpBinding" bindingConfiguration="wsDualHttp"
contract="WCFSvc.IWCFService" />
<endpoint binding="netTcpBinding" bindingConfiguration="netTcp"
contract="WCFSvc.IWCFService" />
<endpoint binding="netNamedPipeBinding" contract="WCFSvc.IWCFService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:26345/WCFSvc" />
<add baseAddress="net.tcp://127.0.0.1:36345/WCFSvc" />
<add baseAddress="net.pipe://localhost/DataService/Service.svc" />
</baseAddresses>
</host>
</service>
</services>
Could be several things, here are a few that you could try:
Is there any local firewall on the machine blocking the request?
Is there a confilct with the net.pipe configuration?
Is there something in the binding configuration that could be causing the problem?
What error are you getting? Is there any error being written to the eventlog?