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

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.

Related

WCF Service Hosted on IIS10. Can browse the .svc file but the wsdl does not show up

I have a test WCF service that I hosted on IIS. I added a new application to the default website and used default app pool to host my test service. I am able to browse the .svc file from the content view in IIS and the success page along with a link to wsdl opens up on Windows IE. However, on clicking the wsdl link, a HTTP 404(Not found) error is thrown.(everything is on my localhost being accessed internally)
I have added the metadata endpoint and this is the relevant portion of my web.config file.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="mexBehaviour" name="ClassLibrary1.HelloWorldService">
<endpoint address="HelloService" binding="basicHttpBinding" bindingConfiguration=""
contract="ClassLibrary1.IHelloWorldService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:17000"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Can someone please guide me about what I can be missing? Could it be a permissions issue or anything else?
Thanks.
There is no need to add the base address to service contract which will be provided by the IIS web server.
The default wcf application configuration enable the service metadata and we are able to access the metadata by the svc page or we directly use the following url.
http://localhost:90/Service1.svc?wsdl
Feel free to contract me If the problem still exists.

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.

Converting WCF SOAP Service Library to REST Service library for MVC

Problem Statement:
We have built MVC 4 application using WCF Service library (not WCF Service Application with svc file). All of the MVC CRUD operations we are doing through WCF SOAP Service library.Everything is working fine.Now suddenly client has changed requirement and asking us to convert WCF SOAP to REST.
I went through many URL's for converting WCF SOAP to REST.In all the URL's they have mentioned converting WCF SOAP Service Application to WCF REST not the WCF SOAP Service library to WCF REST.
My question is can we convert WCF Service library in SOAP to REST.??Is Conversion is same for both WCF Service library and WCF Service Application.??If possible does it impact too much,in changing the existing code??
It would be great if anyone can suggest the better way of converting WCF SOAP to REST in MVC with some URL's and explanation.
Not sure if it helps, but i have done WCF library which is exposed to Soap and REST at the same time. REST exposes XML/JSON and return type depends on input request.
It can be configured via config file, mine looked like this:
<behaviors>
<serviceBehaviors>
<behavior name="BehaviourService">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="BehaviourEndPoint"></behavior>
<behavior name="BehaviourWebHttp">
<webHttp defaultBodyStyle="Wrapped" faultExceptionEnabled="True" automaticFormatSelectionEnabled="True"/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="NameSpace.MyClass" behaviorConfiguration="BehaviourService" >
<!--SoapUI-->
<endpoint name="Name" address ="soap" binding="basicHttpBinding" contract="NameSpace.IMyClass"></endpoint>
<!--Rest-->
<endpoint name="Name" address="" binding="webHttpBinding" behaviorConfiguration="BehaviourWebHttp" contract="NameSpace.IMyClass" ></endpoint>
<!--MEX-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:89/MyAddress"/>
</baseAddresses>
</host>
</service>
</services>
And service like:
[ServiceContract(Namespace = "http://www.mycompany.com", Name = "MyName")]
[DataContractFormat]
public interface IMyClass
{
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "MyMethod", Method = "POST")]
bool MyMethod();
}

WCF 3.5 running SOAP and REST services side by side in IIS

I know that similar question was asked here :
Running SOAP and RESTful on the same URL
Hosting WCF soap and rest endpoints side by side
but didn't find an answer to my problem.
I have two custom servicehostfactories that enables Dependency Injection :
public class StructureMapSoapServiceHostFactory : ServiceHostFactory
public class StructureMapRestServiceHostFactory : WebServiceHost2Factory
The implementation details are not important here.
Then I definied two endpoints in web.config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexGet">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<mexHttpBinding>
<binding name="mexHttpBinding" />
</mexHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="mexGet" name="ServiceImplementation.ServiceCategory">
<endpoint address="rest"
binding="webHttpBinding"
contract="Contracts.ServiceContracts.Mobile.IServiceCategory"
behaviorConfiguration ="jsonBehavior"/>
<endpoint address="soap"
binding="basicHttpBinding"
contract="Contracts.ServiceContracts.Mobile.IServiceCategory" />
<endpoint name="mexHttpBinding"
address="mex"
binding="mexHttpBinding" bindingConfiguration="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Then I created two .svc files for each custom host factories :
ServiceCategoryRest.svc
ServiceCategorySoap.svc
I don't like it. What I would like to do is to have URL in that style :
REST : http://server:port/rest/categories/{id} which mapps to the implementation of my ServiceCategory.GetCategory(int id)
SOAP : http://server:port/soap/GetCategory?id=someId
My questions are. Do i need different svc files to activate host services ? If I need there two .svc files, how can I achieve the URI above ? I'm afraid that I should configure IIS rewriting or something but would like to avoid that.
Thanks in advance for your help.
Thomas
You can achieve what you're looking for with service routes - part of ASP.NET routing, available from ASP.NET 3.5 SP1 on up.
Check out these resources:
RESTful WCF Services with No svc file and no config
Drop the Soap: WCF, REST, and Pretty URIs in .NET 4
making a WCF REST stand-alone service exe from scratch – part 1 of 4, creating the minimal bare service
Using Routes to Compose WCF WebHttp Services
In .NET 3.5 SP1, you need to add some extra infrastructure to your web.config (web routing module etc.) - while in .NET 4, this is all already built in.
After few searches I found out that in fact I don't need two different .svc files and two different ServiceHostFactories.
I kept only the StructureMapRestServiceHostFactory : WebServiceHost2Factory and ServiceCategoryRest.svc which handles well requests in REST mode and call in RPC-SOAP mode.
So if you want to run side by side the REST and the SOAP you can do it only with WebServiceHost2Factory.
If then you want to get rid of the .svc part from the URL, please read the Rick Strahl post west-wind.com/weblog/posts/570695.aspx.

WCF multip proj app and app.config contracts

On my dev box I have a solution with 6 projects. It is a WCF(3 proj) and multiple biz projects (other 3).
When I copy the core WCF folder, it's bin and web.config I get an error message on the server saying that it cannot find the contract that is stated in the app.config section of the biz app with an app.config.
Where should I put this app.config? I tried to add the node to the web config but no go there.
If you're trying to host that services into a web application, you'll need to merge manually that individual app.config files (one for each WCF project) into your web.config file, under <system.serviceModel> section.
EDIT: You'll need something like this into your host configuration (web project?)
<system.serviceModel>
<services>
<service name="YourCompany.YourProject.YourService"
behaviorConfiguration="YourBehaviorConfiguration">
<endpoint address=""
binding="wsHttpContextBinding"
contract="YourCompany.YourProject.IYourService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="YourBehaviorConfiguration">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>