WCF Service Help page for net.tcp binding - wcf

Is it possible to configure a WCF service (with net.tcp bindings) in such a way that it can display a help page as it shows in case of http bindings?

Add a mex endpoint to your service
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
Then add httpGetEnabled to the service's metadata
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
Then you should be able to browse the mex endpoint's url with http
EDIT: changed binding to mexHttpBinding instead of mexTcpBinding

Related

Is there way to convert just some service methods in a WCF to webMethods? Or add webmethods to an existing WCF? [duplicate]

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.

How config file would look at service end for multiple endpoint

i am working with wcf service application where svc file is created. now i want to design my service in such a way that people can connect to my service by http url and as well as by tcp url
so i would like to add three endpoint in my config one for wshttp, one for wsDualhttp and another one for tcp. so please someone give me sample config entry with 3 endpoints for wshttp, wsDualhttp and tcp.
in this case do i need to have three different mex endpoint for wshttp, wsDualhttp and tcp.
also tell me 3 url by which i can create proxy classes at client side. thanks
You could have something like this (assuming self-hosting, since only then can you really determine the full service addresses yourself - hosting in IIS, the service address(es) are most determined by where your .svc file lives):
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="YourNamespace.YourService" behaviorConfiguration="Default">
<endpoint name="Default"
address="http://YourServer/Services/MyService"
binding="basicHttpBinding"
contract="YourNamespace.IYourService"/>
<endpoint name="TCP"
address="net.tcp://YourServer/ServicesTCP/MyService"
binding="netTcpBinding"
contract="YourNamespace.IYourService"/>
<endpoint name="mex"
address="http://YourServer/Services/MyService/mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
<endpoint name="Dual"
address="http://YourServer/Services/MyService/Dual"
binding="wsDualHttpBinding"
clientBaseAddress="http://localhost:8001/client/"
contract="YourNamespace.IYourDualService"/>
</service>
</services>
</system.serviceModel>
This would define three endpoints:
a HTTP endpoint at http://YourServer/Services/MyService for your service
a HTTP MEX endpoint at http://YourServer/Services/MyService/mex for the metadata exchange (service discoverability)
a Net.TCP endpoint at net.tcp://YourServer/ServicesTCP/MyService for your service
You could of course also use two base addresses to make things a bit easier in the config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="YourNamespace.YourService" behaviorConfiguration="Default">
<host>
<baseAddresses>
<add baseAddress="http://YourServer/Services"/>
<add baseAddress="net.tcp://YourServer/ServicesTCP"/>
</baseAddresses>
</host>
<endpoint name="Default"
address="MyService"
binding="basicHttpBinding"
contract="YourNamespace.IYourService"/>
<endpoint name="TCP"
address="MyService"
binding="netTcpBinding"
contract="YourNamespace.IYourService"/>
<endpoint name="mex"
address="MyService/mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
This would configure the equivalent service endpoints.
The wsDualHttpBinding is different in that it requires at least a clientBaseAddress for the callback mechanism (the WCF service will call back your client to send back e.g. status messages) - so it needs some extra tweaks and it cannot really be bolted onto an existing service that works over wsHttpBinding - it needs to be done separately. But basically - it's still pretty much all the same thing....
Update: after reading up on the topic (it's not something I use very often), it does appear that duplex communication is indeed possible also using netTcpBinding, but only if you're self-hosting your service - IIS doesn't support duplex communication over netTcpBinding.
Creating a duplex service does still require extra steps and extra code - so you cannot really have a service that's both non-duplex using basicHttpBinding or wsHttpBinding and duplex at the same time. So it really doesn't make sense to have another endpoint in this example using the wsDualHttpBinding because that service either needs to be really duplex (then you can use wsDualHttpBinding and netTcpBinding) - or it's not duplex - then you can use basicHttpBinding, wsHttpBinding, netTcpBinding and a few more "exotic" bindings (like MSMQ, named pipes etc.)

Host WCF service in console Application

I have around 15-20 services - each service has its own contract and implementation file. I want to host all these service in a console app so that it will be easier to debug during development.
Project structure
Services - Solution
ServiceContracts - Project
Implementation - Project
ServiceHost - Windows Service project -- Already inplace and working fine..
ServiceConsoleHost - Project - Currently working on it.
I have an app.config file in the ServiceConsoleHost project here the sample text from config file...
<service name="TestpricingService" behaviorConfiguration="HostBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/testService/pricingService"/>
</baseAddresses>
</host>
<!-- use base address provided by host -->
<endpoint address="net.tcp://localhost:820/testService/pricingService"
binding="netTcpBinding"
bindingConfiguration="HostBinding"
contract="Test.Services.Contracts.IpricingService" />
<!-- the mex endpoint is exposed at http://localhost:8000/testService/purchasing/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
<behaviors>
<serviceBehaviors>
<behavior name="HostBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
<behavior name="PooledHostBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<ObjectPoolingServiceBehavior minPoolSize="0" maxPoolSize="5" idleTimeOut="30000"/>
</behavior>
</serviceBehaviors>
</behaviors>
Thanks in advance...
You are probably looking for self-hosted services. See MSDN Reference on self-hosting using ServiceHost.
Also take a look at enumerating WCF configuration bindings. Here is an SO post which describes enumerating WCF service and endpoint bindings.
as everyone mentioned you need 15 ServiceHosts to host 15 services. However they are not blocking. If you notice the MSDN code just sits waiting for a keypress whilst the service is running. This means all the service code is running on separate threads. So creating and hosting 15 services is not an issue. You dont need a "loop" as that is already handled once you do ServiceHost.Open().

How to publish WSDL for WCF 4.0 service with REST/SOAP endpoints

I'm creating a WCF4 service with REST and SOAP endpoints to be hosted in IIS 7.5.
I have used the WCF4 REST template as an example.
However I have a few questions regarding my setup so far.
Here's my webconfig
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MEXGET">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MEXGET" name="Project.WebService.VehicleService">
<endpoint
address=""
behaviorConfiguration="REST"
binding="webHttpBinding"
contract="Project.WebService.IVehicleService" />
<endpoint
address="soap"
binding="basicHttpBinding"
contract="Project.WebService.IVehicleService" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
I have removed the standardEndpoints section and added endpoints of my own.
There are no .svc files as I've set the routes in the global.asax as shown below
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("VehicleService", new WebServiceHostFactory(), typeof(VehicleService)));
}
The help pages can be accessed via http://localhost:1313/ServiceTest/VehicleService/help
I've also used the WCF Test Client to access http://localhost:1313/ServiceTest/VehicleService/mex
which shows the metadata for the SOAP endpoint
But how do I retrieve the WSDL of the service?
With an svc file I can find the wsdl at http://localhost:1313/ServiceTest/VehicleService.svc?wsdl However I do not have a .svc file.
And neither can I find the WSDL at http://localhost:1313/ServiceTest/VehicleService?wsdl or http://localhost:1313/ServiceTest/VehicleService/soap?wsdl
Do I need to add a .svc file if I want to publish WSDL for the SOAP endpoint?
I have managed to get the WSDL working at http://localhost:1313/ServiceTest/VehicleService?wsdl.
The solution was using new ServiceHostFactory instead of new WebServiceHostFactory in the global.asax.
With WebServiceHostFactory you lose the WSDL functionality.
A similar question can be found here:
ServiceRoute + WebServiceHostFactory kills WSDL generation? How to create extensionless WCF service with ?wsdl
You should be able to get the WSDL by using the mex URL directly from the browser:
http://localhost:1313/ServiceTest/VehicleService/mex
The WcfTestClient is almost certainly doing that to retrieve the WSDL so it can generate the proxy to the service.

WebHttpBinding not reaching the client

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.