I am very new to WCF and I have questions about it.
After going through some articles I found that in the web.config file if I change the endpoint binding to webHttpBinding from basicHttpBinding and httpGetEnabled from true to false it uses REST.
My question is are these the only two things that I need to change to make a service SOAP or REST? Or do I need to change/add any other things?
You can expose the service in two different endpoints. the SOAP one can use the binding that support SOAP e.g. basicHttpBinding, the RESTful one can use the webHttpBinding. I assume your REST service will be in JSON, in that case, you need to configure the two endpoints with the following behaviour configuration
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
An example of endpoint configuration in your scenario is
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
Apply [WebGet] to the operation contract to make it RESTful. e.g.
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
SOAP request client endpoint configuration for SOAP service after adding the service reference,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
</client>
in C#
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Related
My server used to communicate only with WCF client, and I added an additional access from the web using REST API. So currently the service's web.config contains two endpoints (one for each):
<services>
<service name="Server.Service">
<endpoint address="" bindingConfiguration="BasicHttpBinding_IServWCF" binding="basicHttpBinding" contract="Server.IWCF" />
<endpoint address="api" behaviorConfiguration="WebBehave" binding="webHttpBinding" contract="Server.IREST" />
</service>
</services>
The WCF client bindings:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServWCF" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1862/ServWCF.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IServWCF"
contract="WCFServ.IWCF" name="BasicHttpBinding_IServWCF" />
</client>
Everything works OK, and I can access the server's methods from both ways - WCF and HTTP requests.
The problem - I tried to use the Update Service References feature, but it fails. I get the following error message:
The client and service bindings may be mismatched. the remote server returned an error 415
When I remove the new endpoint - behaviorConfiguration="WebBehave", the update service reference works fine. Can I somehow configure the Update References to use a specific end point?
Thanks
I'm struggling to have my WCF web service output a wsdl file with no luck so far (it's empty?).
the svc file:
<%# ServiceHost Language="C#" Debug="true" Service="xxx.WCF.SubsetMID" CodeBehind="SubsetMID.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
%>
the cs file :
namespace xxx.WCF
{
[ServiceContract(Namespace = "SubsetMID")]
public interface ISubsetMID
{
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped)]
long[] GetMIDs(Guid guid, int subsetID);
}
[DataContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SubsetMID : ISubsetMID
{
public long[] GetMIDs(Guid guid, int subsetID)
{
[...]
return returnValue;
}
}
}
My web config file :
<system.serviceModel>
<services>
<service name="xxx.WCF.SubsetMID">
<endpoint address=""
binding="wsHttpBinding"
contract="xxx.WCF.ISubsetMID" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"
/>
</system.serviceModel>
I don't get any error when I access the wsd (http://.../SubsetMID.svc?wsdl) but it's just a blank page.
The following is a best guess based on some research I did - I'm not that familiar with RESTful WCF services, so I might be wrong but this should give you a starting point at least.
You didn't specify, but it looks like you're trying to write a RESTful WCF service. I'm not entirely certain, because you use wsHttpBinding in your endpoint, but you also decorate the method in the service with [WebInvoke].
In any event, REST services do not have WSDLs - that's a SOAP thing. Additionally, I believe WCF supports REST with the webHttpBinding. As you are using WebServiceHostFactory in your .svc file, I think this is what is happening:
You do not have any webHttpBinding endpoints defined. WCF will create a default webHttpBinding endpoint, with the address based on the location of the .svc file. However, when default endpoints are used according to WebServiceHost Class:
...the WebServiceHost also disables the HTTP Help page and the Web Services Description Language (WSDL) GET functionality so the metadata endpoint does not interfere with the default HTTP endpoint.
If you're writing a REST service, you won't need a WSDL. If you're planning on having a SOAP service, then use ServiceHostFactory in your .svc file and remove the [WebInvoke] attribute from the method.
Again, this is a (relatively) educated guess, and it may be wrong, but it's a place to start.
Im guessing that you are using a wcf service website project which contains the svc file. if you dont, i strongly recommend you to do that and set it as the startup project in your solution, so you could debug it properly. for me, and good chances that for you too if you followed codeproject step by step instructions, the problem was that i didn't reference the wcf services from the website, thus the directive in the svc couldn't find the service. hope i helped
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.
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 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();
}
}