I'm a bit confused of how to expose an endpoint in WCF
I've got a tcp endpoint and a mex tcp endpoint.
<service name="MessageReaderService.MessageReaderService">
<endpoint name="NetTcpReaderService"
address="ReaderService"
binding="netTcpBinding" bindingConfiguration=""
contract="Contracts.IMessageReaderService" />
<endpoint name="netTcpMex"
address="mex"
binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8082" />
</baseAddresses>
</host>
</service>
When I try to run this in the service host I get the following exception :
The contract name 'IMetadataExchange' could not be found in the list of contracts
implemented by the service MessageReaderService. Add a ServiceMetadataBehavior to the
configuration file or to the ServiceHost directly to enable support for this contract.
So I conclude from this error that I need to add a service behavior to expose metadata.
So I added the behavior :
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
but then I get a different error :
The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the
HttpGetUrl property is a relative address, but there is no http base address. Either
supply an http base address or set HttpGetUrl to an absolute address.
So now I have to actually add another endpoint (http) to expose the metadata over mexhttpbinding ?
is there a simple way to expose the endpoint over tcp ?
Two things:
(1) once you've defined the service behavior, you of course must also apply it to the service!
<service name="MessageReaderService.MessageReaderService"
behaviorConfiguration="ServiceBehavior">
(2) you don't need an HTTP endpoint - you don't need to have an HTTP URL - just define this service behavior like this:
<behavior name="ServiceBehavior">
<serviceMetadata />
</behavior>
Your metadata is now available over a mexTcpBinding endpoint - you cannot browse to it using HTTP, but a client can definitely connect to it and use it!
You can verify this by using the WCF Test Client and going to either
net.tcp://localhost:8082 (the base address)
or
net.tcp://localhost:8082/mex (the mex address)
in both cases, the WCF Test Client should now find your service and be able to discover its capabilities.
Related
I am trying to host a svc service in my web application and I am trying to connect to it with a simple client application.
When the host is hosted in my own computer and solution, and I run the web application locally, everything works fine, meaning that I can add the reference to the service using add service reference in my client solution with http://localhost:6543/Hello.svc as the address and when I navigate to the service's url, it shows me the service's information as it should.
But when I publish my website, and I try to add the reference to my service using add service reference with http://myserver.com/Hello.svc as the address, i get the error message bleow:
There was an error downloading
'http://myserver.com/Hello.svc/_vti_bin/ListData.svc/$metadata'. The
request failed with HTTP status 404: Not Found. Metadata contains a
reference that cannot be resolved: 'http://myserverc.com/Hello.svc'.
The remote server returned an unexpected response: (405) Method Not
Allowed. The remote server returned an error: (405) Method Not
Allowed. If the service is defined in the current solution, try
building the solution and adding the service reference again.
and oddly when I navigate to myserver.com/Hello.svc, the browser starts to download the Hello.svc file instead of showing the service's details and information.
this is my website's web.config file:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WithDebug">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="HelloWorldService.HelloService" behaviorConfiguration="WithDebug">
<host>
<baseAddresses>
<add baseAddress="http://myserver/Hello.svc"/>
</baseAddresses>
</host>
<endpoint
address=""
binding="webHttpBinding" bindingConfiguration="crossDomain"
contract="HelloWorldService.IHelloWorld" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
I think I am missing something big here, but since I am new to WCF, I don't know what it is.Any help would be appreciated and I am more than happy to issue more details about my project if needed.
Thanks in advance
You need to run ServiceModel registration tool
"This command-line tool provides the ability to manage the registration of WCF and WF components on a single machine. Under normal circumstances you should not need to use this tool as WCF and WF components are configured when installed. But if you are experiencing problems with service activation, you can try to register the components using this tool."
Simple problem :
How to self host a netTcpBinding service in client project right clicking Service References > Add Service Reference ...
Clicking "Discover" it references all services using WsHttpBinding including the netTcpBinding one. But when expanding the netTcpBinding one it can't navigate to the contract and it throw the following error :
Could not find a base address that matches scheme net.tcp for the
endpoint with binding MetadataExchangeTcpBinding. Registered base
address schemes are [http].
I found the following .Net WCF sample very nice and neat, but in the example, it doesn't show how the config file is set, and how we could get the proxy via the wizzard.
C:\WF_WCF_Samples\WCF\Basic\Binding\Net\Tcp\Default\CS
Here is the service config file ... (I don't use any base adress, it should work without it I think)
<service behaviorConfiguration="Canopus.WebServices.LogAndNotificationService"
name="Canopus.WebServices.LogAndNotificationService">
<endpoint address="" binding="netTcpBinding"
contract="Canopus.WebServices.ILogAndNotificationService" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
<behaviors>
<serviceBehaviors>
<behavior name="Canopus.WebServices.LogAndNotificationService">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Thanks for your help !
I think your service behaviour cannot have httpGetEnabled attribute when u r dealing with netTcPBinding. and also looks like ur end point address contains something like http:// it should be net.tcp://.
I've written a WCF service. I have successfully browsed to the service and it says:
You have created a service.
So then I add a reference to it using a the 'Add Service Reference' in visual studio. Then I write the following code to consume it....
ServiceReference1.VLSContentServiceClient client = new ServiceReference1.VLSContentServiceClient("VLSContentServiceEndpointBehaviour");
List<ServiceReference1.Category> cats = client.GetCategoriesByGET();
But im getting the error:
Could not find endpoint element with
name
'VLSContentServiceEndpointBehaviour'
and contract
'ServiceReference1.IVLSContentService'
in the ServiceModel client
configuration section. This might be
because no configuration file was
found for your application, or because
no endpoint element matching this name
could be found in the client element.
It makes no sense because the argument 'endPointConfigurationName' matches what I have set it to in the service. Here is the service configuration:
<system.serviceModel>
<services>
<service behaviorConfiguration="VLSContentServiceBehaviour" name="VLSContentService">
<endpoint address="" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="VLSContentServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="VLSContentServiceEndpointBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Whats going on?
You are using REST service - client for such service cannot be created with Add service reference. That is only for SOAP services (no webHttpBinding and webHttp behavior). Also once you use SOAP service you don't pass name of any server side feature to the constructor of the proxy. The proxy constructor expects name of client endpoint from client's configuration.
How to consume REST service
Looks like your contract is not correct. you have:
contract="IVLSContentService"/>
and it is expecting:
contract="ServiceReference1.IVLSContentService"/>
according to the error message.
also your endpoint address is empty. Does that not need to contain something?
The VLSContentServiceEndpointBehaviour parameter while creating an instance of client is the Name of the endpoint and not the endpoing behaviour.
Change
<endpoint address="" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
to
<endpoint address="" name ="Client" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
and create a service client as
ServiceReference1.VLSContentServiceClient client = new ServiceReference1.VLSContentServiceClient("Client");
Also your address is missing which is bit strange.
I'm having a couple of issues which may be related, or may not. I noticed that when I use Add Service Reference in Visual Studio to add a reference to my data service, the reference.cs it generates does not compile. It complains about a missing namespace. I can fix it up to compile, but this happens every time I update the reference, and it's worrying on other levels too, such as "will this cause other issues".
I also noticed that when I do this, my host server (a console application hosting the data service) logs this:
An exception occurred [System.Data.Services.DataServiceException] :: The URL
representing the root of the service only supports GET requests.
This is the service config:
<service behaviorConfiguration="behaviour" name="StatsPlus.Server.HostedServices.SPDataServiceHost">
<endpoint address="svc" binding="webHttpBinding" contract="System.Data.Services.IRequestHandler" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8752/DataService/"/>
</baseAddresses>
</host>
</service>
And the behaviour:
<behavior name="behaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="10"/>
</behavior>
When I try to run svcutil http://localhost:8752/DataService/, I get this:
HTTP GET Error
URI: http://localhost:8752/DataService
There was an error downloading 'http://localhost:8752/DataService'.
The request failed with HTTP status 405: Method Not Allowed.
Any ideas? Much appreciated
Thanks
I think you're connecting to a wrong address. You have a base address
<add baseAddress="http://localhost:8752/DataService/"/>
and on top of that a relative endpoint address
<endpoint address="svc" binding="webHttpBinding"
so your complete URL will be the combination of the two:
http://localhost:8752/DataService/svc
Did you try to connect there??
I am not sure if you can have a "mex" metadata exchange endpoint with WCF REST services, really. I was under the impression that the client-side proxy for a WCF Data Service gets its metadata over a special URL call from the HTTP endpoint. So maybe try to remove that from your config as well (and you can't use svcutil on that service, I believe - svcutil is only for SOAP service calls, if I'm not mistaken).
Also, since you're using webHttpBinding and self-hosting, you need to add the webHttp behavior:
<behavior name="behaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="10"/>
<webHttp />
</behavior>
If you do these two steps, I think you should be able to get at your WCF Data Service. Try it and let us know!
I have a test project, WCF Service Library, and I published the project. Have a 2003 server with all the right installation. I browse to my application and upon clicking on .svc I get this error.
The type 'SearchService', provided as the Service attribute value in the ServiceHost directive could not be found.
This is the snippet from my web.config
<endpoint address="" binding="wsHttpBinding" contract="TestService.ISearchService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
My Interface:
[ServiceContract]
public interface ISearchService
{
[OperationContract]
string GetName();
}
My Implementation:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class SearchService :ISearchService
{
#region ISearchService Members
public string GetName()
{
returnn "HAL-2001"
}
}
Well, the wsHttpBinding requires you to connect to your service using SOAP - a web browser alone won't cut it, so that's why it's not working when you browse to the .svc file. Nothing wrong there, really.
You need to create a real full-fledged SOAP client to connect to your service and test it. Alternatively, you could also use the WcfTestClient.exe test client which sits in your VS2008\Common7\IDE folder.
Marc
ANo, the error indicates the host could not find the definition for service implementation "SearchService" in your web.config. In you web.config, you need to wrap the <endpoint> tag in a <service> tag. The name attribute of the <service> should be set to the full name of you SearchService class ( including all namespaces). You also need to define a behavior to enable the service to show WSDL in a browser. You may also want to remove the <dns value="localhost" /> when you deploy the service to a server.
Here is an example snippet, make sure your put the full class name of SearchService in <service> tag, and also make sure the full class name is in your .svc file:
<system.serviceModel>
<services>
<service name="SearchService" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="TestService.ISearchService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- 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>
ANo, you should switch over to the basicHttpBinding and test to make sure everything is working. You're using the WSHttpBinding and by default it has authentication turned on. You're client will need to pass credentials for it to actually get a response, that's why the browser call isn't working.
What is your client code calling? For this to work it should be calling a proxy class like the following.
class SearchServiceProxy : ClientBase<ISearchService>, ISearchService
{
public string GetName()
{
return Channel.GetName();
}
}