WCF multiple named pipe endpoints - c#

I have two services I want to interact with through named pipes. I tried this two ways, both by creating two separate ServiceHosts, and by creating multiple endpoints on a single service. The first service works perfectly whether I have the second service or not. For the second service in both cases, I either get an endpoint not found error due to it not finding the named pipe (separate services) or an address filter problem (which setting to Any does not fix). I've checked and double checked my settings, but I'm stumped.
Both the server and client both use the same assembly that has the contract:
[ServiceContract(CallbackContract = typeof(IServiceCallback1), SessionMode = SessionMode.Required)]
public interface IService1
{
....
}
[ServiceContract]
public interface IService2
{
...
}
Here's the server side:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant, IncludeExceptionDetailInFaults = true)]
class Service1Impl : IService1
{
...
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)]
class IService2Impl : IService2
{
...
}
...
serviceHost1 = new ServiceHost(typeof(Service1Impl));
serviceHost2 = new ServiceHost(typeof(Service2Impl));
try
{
serviceHost2.Open();
serviceHost1.Open();
}
(Yes, I open them in the opposite order, since the client process assumes that Service2 is available if it can connect to Service1)
Here's my configuration for the services:
<system.serviceModel>
<services>
<service name="Service1Impl" behaviorConfiguration="myServiceBehavior">
<endpoint address="" binding="netNamedPipeBinding" contract="IService1"/>
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/Service1"/>
</baseAddresses>
</host>
</service>
<service name="Service2Impl" behaviorConfiguration="myServiceBehavior">
<endpoint address="" binding="netNamedPipeBinding" contract="IService2"/>
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/Service2"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client-side I don't use configuration and use this for both:
public class Service2Client: ClientBase<IService2>, IService2
{
public Service2Client()
: base(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Service2"))
{
}
}
Is there something I'm missing here? Like I said, I can connect and make calls on the first service just fine, but the second gets EndpointNotFoundException complaining that it couldn't find the named pipe.

Related

invoke WCF service method from web browser

I want to run my service from the web browser: http://localhost:443/TestService//RunTest/data/test
It doesn`t work for me
This page can’t be displayed
•Make sure the web address http://localhost:443 is correct.
•Look for the page with your search engine.
•Refresh the page in a few minutes.
How to solve that - redefine endpoint - how?
The WCF service:
//TestService.svc.cs
public class TestService : ITestService
{
public string RunTest(string data)
{
return string.Format("You entered: {0}", data);
}
}
//ITestService.cs
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/RunTest/data/{data}")]
string RunTest(string data)
{
return string.Format("You entered: {0}", proxyDomain);
}
//Web.config
<system.serviceModel>
<services>
<!-- This section is optional with the default configuration introduced
in .NET Framework 4.5.1 -->
<service
name="TestService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:443/TestService/"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:443/TestService"
binding="wsHttpBinding"
contract="ITestService" />
</service>
</services>
</system.serviceModel>
Also when I run it a WCF client is opened with port 54388
In my experience, you wouldn't be able to test directly via the browser.
Instead you should use a WCF Test Client:
http://msdn.microsoft.com/en-us/library/bb552364(v=vs.110).aspx
What you can do using your browser, is to see if you can reach the WSDL.
An example of a WSDL call in a browser:
http://localhost:8080/DecisionService/ws/PreTradeChecksRuleApp/1.0/PreTradeChecks/1.0?WSDL
You should add/change the endpoint "binding" attribute to "webHttpBinding" like this:
<endpoint address="http://localhost:443/TestService"
binding="webHttpBinding"
contract="ITestService" behaviorConfiguration="web" />
Or
<endpoint address="http://localhost:443/TestService"
binding="wsHttpBinding"
contract="ITestService" />
<endpoint address="http://localhost:443/TestService/web"
binding="webHttpBinding"
contract="ITestService" behaviorConfiguration="web"/>
In Both Cases you Have to Add:
<behaviors>
...
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
...
</behaviors>
notes:
1) You have to add the attribute behaviorConfiguration to the webBinding and Add the behavior configuration
2) In the second solution, You have to change the name of the baseAddress because you can't have two endpoints configured to the same baseAddress (if anyone knows how to do it, please it would help me too)
Best Regards

How to publish wcf service metadata when the wcf is self-hosted?

I googled for 2 days and tried almost everything, but I still can't get this stuff working.
I have 2 WCF services. I use self-hosting, not IIS(for some reasons IIS isn't working for me). One is duplex, another is standart. Here are their contracts:
Duplex:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceCallback))]
public interface IClientService
{
[OperationContract(IsOneWay = true)]
void SolveTask(string pipelineName, string data);
[OperationContract(IsOneWay = true)]
void GenerateTask(List<GeneratorMethod> parameters);
[OperationContract]
bool Ping();
}
public interface IServiceCallback
{
[OperationContract(IsOneWay = true)]
void SendResult(SampleAnswer[] answers);
[OperationContract(IsOneWay = true)]
void RequestGeneratorParameters();
[OperationContract(IsOneWay = true)]
void SendGenerationResult(string text);
}
Classic:
[ServiceContract]
public interface IServerManagementService
{
[OperationContract]
[FaultContract(typeof(XmlError))]
[FaultContract(typeof(UnknownError))]
[FaultContract(typeof(InitializationError))]
void InitializeServer();
[OperationContract]
void StartServer();
[OperationContract]
void StopServer();
[OperationContract]
void RestartServer();
}
I have following config:
<configuration>
<services>
<service behaviorConfiguration="Service" name="LinProgWebServer.ClientService">
<endpoint address="net.tcp://localhost:8078/LinProgWebServer/ClientService"
binding="netTcpBinding" bindingConfiguration="netTcpEventBinding"
contract="LinProgWebServer.IClientService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService" />
</baseAddresses>
</host>
</service>
<!--сервис управления сервером-->
<!--<service behaviorConfiguration="Service" name="LinProgWebServer.ServerManagementService">
<endpoint address="net.tcp://localhost:8079/LinProgWebServer/ManagementService"
binding="netTcpBinding" bindingConfiguration="netTcpEventBinding"
contract="LinProgWebServer.IServerManagementService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/LinProgWebServer/ManagementService" />
</baseAddresses>
</host>
</service>-->
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Service">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Now i have a big trouble: I CAN find classic service via add service reference and CANNOT find duplex service. I tried netstat and it says that both services are listening on their ports. What am i doing wrong?
Here is exception i get:
There was an error downloading 'http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 405: Method Not Allowed.
Metadata contains a reference that cannot be resolved: 'http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService'.
There was no endpoint listening at http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
If the service is defined in the current solution, try building the solution and adding the service reference again.
I'll be grateful for any help.
Make sure you .svc file has the correct name of the class you added in your Service Reference
if you added a service called 'Foo' it should look like:
<%# ServiceHost Language="C#" Debug="true" Service="Foo" CodeBehind="Foo.svc.cs" %
Also, make sure you have
In your web.config
I'm not sure whether this is going to be usefull. All my configs and services were fine, but i had a mistace in types, which were involved in work of wcf services, i haven't marked one of the types as datacontract. U'm very surprised why service started without erros and showed me such not informative messages. Also, thanks Yuval for reminding about InstanceContextMode attribute.
Add this to the area where you setup you set up your endpoint and reference your service classes:
//config service metadata
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
ServiceMetadataBehavior mb = new ServiceMetadataBehavior();
ServiceHost.Description.Behaviors.Add(mb);
if (bUseSSL) {
mb.HttpsGetEnabled = true;
mb.HttpGetEnabled = false;
ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpsBinding(), "mex");
} else {
mb.HttpsGetEnabled = false;
mb.HttpGetEnabled = true;
ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
}
You should not be using the same URL that you were using to host it in the dev environment. Localhost means nothing outside of the machine, anyway. Use the IP address of the machine and also -- you might have to use netsh to open the port on that machine.

How adding an Interface to a WCF ServiceContract changes the URL of the methods

I am trying to fully understand how adding an Interface in WCF affects the URI of the methods. I have a ServiceContract defined like this:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract]
public class DataService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public List<List<string>> ListTestMethod()
{
return new List<List<string>>
{
new List<string> {"0", "Test String 1"},
new List<string> {"1", "Test String 2"},
new List<string> {"2", "Test String 3"}
};
}
}
In my web.config file I have the following:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="epBehavior" >
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="DataService" />
</service>
</services>
</system.serviceModel>
When I test the method via a browser:
http://localhost/DataService.svc/ListTestMethod
I get this which is the expected result:
[["0","Test String 1"],["1","Test String 2"],["2","Test String 3"]]
So now I would like to add an interface to the code behind with something like this:
[ServiceContract]
public interface IDataService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
List<List<string>> ListTestMethod();
}
And of course go back to the DataService class and add the appropriate ": IDataService" implementation while removing the adorners that are now already in the Interface. Here is where I have trouble as the URL above no longer works.
I tried updating web.confg to this (note changes to name and contract attributes):
<services>
<service name="IDataService.DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="IDataService.DataService" />
</service>
</services>
Which seems to get the service going again but I cant actually get to the methods and if I add enable serviceMetadata it can no longer get to the metadata (it can in the original version). I have tried all kinds of combinations of the web.config and the URL but cannot seem to get my arms around it. How do I wire in the new Interface appropriately?
UPDATE
Thanks to venerik I got it working but changing the endpoint to point at the interface but leaving the service as is:
<services>
<service name="DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="IDataService.DataService" />
</service>
</services>
I'm not fully confident of this answer but I think your web.config should point to the interface:
<endpoint
...
contract="IDataService"/>
Your service host file should point to the concrete implementation:
<% #ServiceHost Language=C# Service="SomeNamespace.DataService" %>
Info about #ServiceHost

WCF Service start error - Service has zero application endpoints

I'm trying to start a windows service and I'm getting the following error:
Service cannot be started. System.InvalidOperationException: Service
'LazyPCAndroiderSvc.LazyPCController' has zero application
(non-infrastructure) endpoints. This might be because no configuration
file was found for your application, or because no service element
matching the service name could be found in the configuration file, or
because no endpoints were defined in the service element.
?
I've already tested the service using WCF Tester and it posed no problem. Only when I try to run this as a windows service, it causes the above error.
Here is my app.config from the wcf service:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="LazyPCAndroiderSvc.LazyPCController"
behaviorConfiguration="LazyPCControllerBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8750/LazyPCAndroiderSvc/LazyPCController/"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="LazyPCAndroiderSvc.ILazyPCController" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="LazyPCControllerBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I've verified that the names match perfectly (Including the namespace).
Here is my WindowsService code:
namespace LazyPCAndroiderWinSvc
{
public partial class Service : ServiceBase
{
ServiceHost sHost;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
sHost = new ServiceHost(typeof(LazyPCAndroiderSvc.LazyPCController));
sHost.Open();
}
protected override void OnStop()
{
sHost.Close();
}
}
}
This seems like a trivial problem but I cannot locate the cause.
Service may not read automatically from LazyPCAndroiderSvc.dll.config - put those configurations in your main exe's App.config

Two WCF services, hosted in one console application

I have one console app as a hosting for WCF service. Now, I'm going to add another one WCf service for administer purposes. So, here is my code:
[ServiceContract]
public interface IServiceAdmin
{
[OperationContract]
int GetCount();
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class ServiceAdmin : IServiceAdmin
{
public int GetCount()
{
// It's just a stub to go on
return 1;
}
}
Here is excerpt of App.config applied to services:
<serviceBehaviors>
<behavior name="MyService.ServBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.MyServ">
<endpoint address="MyServ" behaviorConfiguration="" binding="netTcpBinding" contract="MyService.IMyServ" isSystemEndpoint="false" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.MyServAdmin">
<endpoint address="MyServ" behaviorConfiguration="" binding="netTcpBinding" contract="MyService.IServiceAdmin" isSystemEndpoint="false" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
And here is how I get services started:
static void Main(string[] args)
{
ServiceHost myserviceHost = new ServiceHost(typeof(MyServ), new Uri("net.tcp://192.168.1.40:8730/"));
myserviceHost.Open();
ServiceHost myAdminHost = new ServiceHost(typeof(AServiceAdmin), new Uri("net.tcp://192.168.1.40:31337/");
myAdminHost.Open();
Console.ReadLine();
}
The issue is that regular service working good (metadata exchanging can provide info on service methods) and another service (which I mentioned at the beginning, administer service) is not working at all.
That is the reason of it?
Thanks in advance!
The issue was in wrong name of service in App.Config. The right line is
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.ServiceAdmin">

Categories