I created a web service for which I am trying to provide 3 endpoints with different bindings.
1. basicHttpBinding,
2. wsHttpBinding,
3. webHttpBinding
When I make the service reference, I get only the endpoints with the basicHttpBinding and wsHttpBinding bindings created. I don't get webHttpBinding. What could possibly wrong.
Here's the structure of the serviceModel node in web.config.
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"/>
</diagnostics>
<services>
<service behaviorConfiguration="VersionTolerance.Service1Behavior" name="BookShop.BookShopService">
<endpoint address="sadha" binding="basicHttpBinding" contract="BookShop.IBookShopService" />
<endpoint address="ws" binding="wsHttpBinding" contract="BookShop.IBookShopService" >
</endpoint>
<endpoint address="web" binding="webHttpBinding" behaviorConfiguration="webHttpBehavior"
contract="BookShop.IBookShopService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:49654/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="VersionTolerance.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>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
There's nothing wrong - that's just the way it works!
basicHttpBinding and wsHttpBinding are SOAP bindings that expose metadata about their service - your Visual Studio Add Service Reference can interrogate their endpoints, find out what they're called, what methods they offer, what data types they expect as parameters and what they return.
webHttpBinding is REST - and REST by default doesn't have a concept of metadata - you won't get a service description, list of methods etc. - REST is all about resources - not methods.
So therefore, when you do a Add Service Reference, you get proxy clients for the SOAP endpoints - but not for the REST / webHttpBinding endpoint. Works as designed.
The WCF Data Services - built on top of REST - offer a similar experience to the SOAP bindings, in that you can do an Add Service Reference and get a nice client side proxy and all - and this is done since the OData protocol defines a metadata exchange on top of REST. So if you can turn your REST service into a WCF Data Service, you'd be fine again.
Otherwise, with REST, you just have to "know" (from a documentation page or something) what the resource URI's for your REST service are, and what the HTTP verbs do in your REST context.
Related
Background
I have created ASMX web services in the past and have been able to access the service from the web browser and Ajax GET requests using the address convention: MyService.asmx/MyMethod?Param=xxx
I just got started using WCF and created a new web service in my ASP.NET project. It creates a file with the .svc extension such as MyService.svc.
Current Situation
I am able to consume the service using the WcfTestClient that comes with VS2008. I am also able to create my own WCF Client by either adding a service reference in another project or using the svcutil.exe commandline to generate the proxy and config file.
The Problem
When I try to use the service from a browser using MyService.svc/MyMethod?MyParam=xxx, I get a blank page without any errors.
What I have tried
I have already added a basicHttpBinding to the web.config and made it HttpGetEnabled in the behavior configuration. I also added the [WebGet(UriTemplate = "MyMethod?MyParam={MyParam}")] attribute to my operation contract.
I have already followed the information in this other stack overflow question:
REST / SOAP EndPoints for a WCF Service
However, I either get a blank page or an HTTP 404 Error after following those steps. There's nothing special about the code. I am just taking in a string as a parameter and returning "Hello xxx". This is a basic "Hello WCF World" proof-of-concept type thing.
UPDATE - Here's the relevant code
[ServiceContract]
public interface IMyService
{
[WebGet(UriTemplate = "MyMethod/MyParam={MyParam}")]
[OperationContract]
string MyMethod(string MyParam);
}
Web.Config - system.serviceModel Section
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<endpoint address=""
binding="wsHttpBinding" contract="IMyService" />
<endpoint address="MyService.svc"
binding="basicHttpBinding" contract="IMyService" />
<endpoint address="mex"
binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Looking at your web.config serviceModel section, I can see that you need to add a webHttpBinding and associate an endPointBehavior that includes webHttpGet.
Your operation contract is correct. Here's how your system.serviceModel config section should look in order for you to be able to consume the service from a GET HTTP request.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<endpoint address="ws" binding="wsHttpBinding" contract="IMyService"/>
<endpoint address="" behaviorConfiguration="WebBehavior"
binding="webHttpBinding"
contract="IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Be sure to assign a different address to your wsHttpBinding endpoint, otherwise you will get an error saying that you have two endpoints listening on the same URI.
Another option is to leave the address blank in the wsHttpBinding, but assign a different address to the webHttpBinding service. However, that will change your GET address as well.
For example, if you assign the address as "asmx", you would call your service with the address "MyService.svc/asmx/MyMethod?MyParam=xxxx".
The normal WCF requests are always SOAP requests - you won't be able to get this going with just your browser, you'll need the WCF Testclient for that.
There is an add-on for WCF called the WCF REST Starter Kit (which will also be included in WCF 4.0 with .NET 4.0), which allows you to use GET/POST/PUT/DELETE HTTP commands to query WCF services and such. You need to write your services specifically for REST, though - you can't have SOAP and REST on the same service call.
Marc
As marc_s says, the REST Starter Kit can help, but you should also be aware that .NET 3.5 has support for REST services directly in it. It's not quite as complete as what you can do with the starter kit, but it is useful.
The way it works is that you put a [WebGet] attribute on your operations to indicate where in the URL the various parameters should come from:
[WebGet(UriTemplate = "helloworld/{name}")]
string Helloworld(string name);
See this portal for tons of information.
Note, you can have the same service exposed as both SOAP and REST if you specify multiple endpoints/bindings in the configuration.
I want to run WCF Service from my VS2010 When i run WCF Service using below configuration.
<system.serviceModel>
<services>
<service name="WcfSample.Service1" behaviorConfiguration="servicebehaviour1">
<endpoint address ="http://localhost:8080/service1/Service1.svc" contract="WcfSample.IService1" binding="wsHttpBinding"></endpoint>
<endpoint address="" binding="mexHttpBinding" contract ="IMetadataExchange"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="servicebehaviour1">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="false"/>
<!-- 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>
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="false" />-->
i am getting exception as below
No protocol binding matches the given address 'http://localhost:8080/service1/Service1.svc'. Protocol bindings are configured at the Site level in IIS or WAS configuration.
If i want to run my WCF at my given address wat should i do.
Hosting of WCF service doesnt take the address you define in endpoints of config file
<endpoint
address="http://localhost:8080/service1/Service1.svce"
So the above one you defiend is not correct one instead of this you need to do as below
you address of service is the web server and the virtual directory plus the SVC file name like as below
http://servername/vrirualdirectoryname/svcfiename.svc/
you can define relative addresses like as below :
<service name="WcfSample.Service1">
<endpoint name=""
address="ServiceAddress"
binding="wsHttpBinding"
contract="WcfSample.IService1" />
</service>
so finally you service adress from which you consume service is
http://servername/vrirualdirectoryname/svcfiename.svc/ServiceAddress
so like this you can do rather than specifying address direcly.
Note :
Above code is asuinming that service is going to be hosted on IIS server.
Is it possible to use the new WCF routing serice in WCF 4 for REST based services? I have something similar to a reverse proxy in mind. Basically I have a number of selfhosted rest based serivces which I want to expose via IIS with the same base url and port. The routing should be done by the last part of the url. I'm absolutly new to thw WCF routing service, so forgive me if that's a silly question, but I couldn't find any information about that on the web.
I have tried something like this (where serivce1/2 are the selfhosted services):
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="RoutingBehavior">
<routing routeOnHeadersOnly="false" filterTableName="RoutingTable"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="RoutingBehavior" name="System.ServiceModel.Routing.RoutingService">
<endpoint address="myservices" contract="System.ServiceModel.Routing.IRequestReplyRouter" binding="basicHttpBinding"/>
</service>
</services>
<routing>
<filterTables>
<filterTable name="RoutingTable">
<add filterName="service1Filter" priority="0" endpointName="service1"/>
<add filterName="service2Filter" priority="0" endpointName="service2"/>
</filterTable>
</filterTables>
<filters>
<filter name="service1Filter" filterType="MatchAll"/>
<filter name="service2Filter" filterType="MatchAll"/>
</filters>
</routing>
<client>
<endpoint address="http://somehost:8888/test/service1" binding="basicHttpBinding" contract="*" name="service1"/>
<endpoint address="http://somehost:8732/test/service2" binding="basicHttpBinding" contract="*" name="service2"/>
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
but that doesn't seem to work. I'm getting an endpoint not found exception. http://somehost:8888/test/service1 ist the base address of the selfhosted service and not the actual endpoint. Can I do routing based on the base address or (if rest routing is possible) must I add a route for every endpoint?
I solved the problem by using a reverse proxy (in my case arr). I don't konw if using the WCF routing service for this purpose is possible, but it's probably a misuse.
Routing Service is only available for SOAP requests. To use routing with RESTful WCF you need to setup your routes using System.Web.Routing similar to MVC routing.
What is the use and importance of IMetadataExchange in WCF?
I have the following app.config file in which I don't use IMetadataExchange endpoint, but I am still able to create my proxy client. I have read that if I don't use IMetadataExchange endpoint, AddServiceReference will not work because my service does not expose the metadata. How is it working without exposing IMetadataExchange endpoint?
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metaDataBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name ="WCFService.Services" behaviorConfiguration="metaDataBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8090/Services/"/>
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="WCFService.IMathOperations"/>
</service>
</services>
</system.serviceModel>
</configuration>
ArsenMkrt has the formal answer. Put more simply:
If you don't have it, adding a service reference will not work
You should delete it from production servers, so that a hacker cannot add a service reference
To answer your question more specifically, you have this line on your service:
<service name ="WCFService.Services" behaviorConfiguration="metaDataBehavior">
Which points to this configuration
<behavior name="metaDataBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
This may be why it still works, although I thought that you needed to specify the MEX endpoint.
IMetadataExchange Interface Exposes methods used to return metadata about a service.
When programming Windows Communication Foundation (WCF) services, it is useful to publish metadata about the service. For example, metadata can be a Web Services Description Language (WSDL) document that describes all of the methods and data types employed by a service. Returning metadata about an WCF service allows consumers of a service to easily create clients for the service.
The difference is:
<serviceMetadata httpGetEnabled="true"/>
allows you to retrieve metadata using the HTTP protocol.
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
allows you to retrieve metadata using the ws-metadata protocol.
Just <serviceMetadata httpGetEnabled="true"/> works, but not all clients can call you (because they can't retrieve metadata to create a proxy).
The standard is to publish both.
See also ServiceMetadataBehavior Class (MSDN).
Without IMetadataExchange, a WCF service exposes the metadata information to the client, but WCF does not guarantee to expose the metadata because WCF default features to exposing the metadata to the client.
Exposing the metadata is done in a well-standardized way through IMetadataExchange. The IMetadataExchange interface follows the industry standard.
I want to use netTCPbinding, so I've changed my web config as below. I'm experiencing this error:
Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
How can this be solved?
<services>
<service name="DXDirectory.DXDirectoryService" behaviorConfiguration="DXDirectory.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="netTcpBinding" bindingConfiguration="WindowsSecured" contract="DXDirectory.IDXDirectoryService">
<!--
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>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:2582/DXDirectoryService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DXDirectory.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="false" />
<!-- 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" />
<serviceAuthorization principalPermissionMode="UseWindowsGroups" />
<!--<serviceCredentials>-->
<!--<userNameAuthentication userNamePasswordValidationMode="Custom"
membershipProviderName="CustomUserNameValidator"/>-->
<!--</serviceCredentials>-->
</behavior>
</serviceBehaviors>
</behaviors>
HMm... you've added the base address to your services/host section ok.
Quick question: are you self-hosting, or hosting in IIS ?? Which version of IIS ??
IIS5/6 only support HTTP connections - you cannot host a NetTCP in IIS 5/6.
In IIS7, you have to manually go through a series of steps to enable non-HTTP bindings, but it's possible. See this MSDN article on how to achieve this.
Self-hosting is the best option - you get all bindings and are in total control of your service being hosted.
Marc
Here is a NetTcpBinding basic example from msdn. See if this can help you.
EDIT:
And here is a related SO question.
I cant see section in your config file, can u please
please add this
<netTcpBinding>
<binding name="WindowsSecured">
<security mode="none"/>
</binding>
</netTcpBinding>