Where in the web.config should the following blocks of code go for a WCF RESTful service?
<endpoint address="" binding="webHttpBinding"contract="Wcf_Test.IMyService"
behaviorConfiguration="httpEndpointBehavour">
<identity>
<dns value="localhost"/>
<Identity>
</endpoint>
and
<behaviors>
<serviceBehaviors>
<behavior name="httpBehaviour"> <serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
and
<endpointBehaviors>
<behavior name="httpEndpointBehavour">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
In order to configure a WCF REST service, you need a few things in your web.config file
1) Declare your service and its endpoint
<services>
<service name="SparqlService.SparqlService" behaviorConfiguration="ServiceBehavior">
<endpoint binding="webHttpBinding" contract="SparqlService.ISparqlService"
behaviorConfiguration="webHttp"/>
</service>
</services>
Service name will be [project name].[service name]
Behavior configuration will be same name as the behavior you declare in the next step
Binding must be webHttpBinding because you want it as REST. If you want SOAP, you declare as basicHttpBinding
Contract is the [project name].[interface name]
Behavior configuration in the endpoint will be the name you declare in next step
2) Declare the service behavior (usually default)
<behavior name="ServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
Behavior name can be anything, but it will be used to match BehaviorConfiguration you declared in step 1
Leave the rest alone
3) Declare your endpoint behavior
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
Behavior name can be anything, but it will be used to match the behaviorConfiguration in endpoint.
In the end, this is what the web.config should look like for a simple REST service:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="SparqlService.SparqlService" behaviorConfiguration="ServiceBehavior">
<endpoint binding="webHttpBinding" contract="SparqlService.ISparqlService"
behaviorConfiguration="webHttp"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior>
<!-- 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="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
for the rest type using WCFservice
<configuration>
<system.serviceModel>
<services>
<service>
<--
"place the first code snippet here "
it will contain the endpoint details
for WCFrestfulServices it will have 'A' ,'B' and 'C'
that is address, binding and contract
-->
</service>
</services>
<behaviors>
<servicebehaviours>
<--
"place the second code snippet"
the name of the behavior should be the same to that of the
behavior configuration attribute value of service tag
-->
</servicebehaviours>
<endpointBehaviors>
<--
"place your third code snippet"
the name of the behavior should be the same to that of the
behavior configuration attribute value of endpoint tag
-->
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Web config changes.
<system.serviceModel>
<services>
<service name="WcfService1.Service1">
<endpoint address="" behaviorConfiguration="restbehavior" binding="webHttpBinding" bindingConfiguration=""
contract ="WcfService1.IBookService">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost/bookservice"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="restbehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Interface: we have to use WebGet for httpGet / WebInvoke for HttpPost & Put & Delete.
[ServiceContract]
public interface IBookService
{
[OperationContract]
[WebGet]
List<BOOK> GetBooksList();
[OperationContract]
[WebGet(UriTemplate = "Book/{id}")]
BOOK GetBookById(string id);
[OperationContract]
[WebInvoke(UriTemplate = "AddBook/{name}")]
void AddBook(string name);
}
Ref : https://www.codeproject.com/Articles/571813/A-Beginners-Tutorial-on-Creating-WCF-REST-Services
Related
When calling service url https://example.com/TestService.svc I am getting the below 2 URLs but when I am trying to click on WSDL then it is not working.
WSDL URLs
http://example.com/TestService.svc?wsdl -- NOT WORKING
http://example.com/TestService.svc?singleWsdl -- NOT WORKING
Manually change http to https
https://example.com/TestService.svc?wsdl -- WORKING
https://example.com/TestService.svc?singleWsdl -- WORKING
Client Config
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</client>
<behaviors>
<serviceBehaviors>
<clear/>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
Main Service Config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<clear />
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0">
<serviceActivations>
<clear />
<add factory="DataServicesHost.UnityServiceHostFactory" relativeAddress="TestService.svc" service="TestService.Service" />
</serviceActivations>
</serviceHostingEnvironment>
Service Consuming
var customHeader = new MessageHeader<Security>(security);
var tempHeader = customHeader.GetUntypedHeader("Security", "http://tempuri.org/");
var client = new ServiceClient();
using (var scope = new OperationContextScope(client.InnerChannel))
{
OperationContext.Current.OutgoingMessageHeaders.Add(tempHeader);
objDataRequest = client.DataRequest("test");
}
From the above configuration, we can infer that it belongs to the client-side. However, the WSDL feature of the WCF service is set up on the server-side. It is controlled by the ServiceMetadata section.
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
Therefore, if we want to have the HTTP protocol of WSDL feature working, we need to enable it on the server-side and apply the service behavior in the service section(the endpoint should be within the service section instead of client section).
<system.serviceModel>
<services>
<service name="WcfService3.Service1" behaviorConfiguration="sb">
<endpoint address="" binding="basicHttpBinding" contract="WcfService3.IService1"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="sb">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
Feel free to let me know if there is anything I can help with.
I have this WCF service with a SOAP endpoint and I'm succesfully exposing both methods with the following code/config:
Service Contract
[ServiceContract]
public interface IService
{
[OperationContract]
string TestConn();
[OperationContract]
string AddRecord();
}
Web.config
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WSADPITG.Service" behaviorConfiguration="ServiceBehavior">
<endpoint binding="basicHttpBinding" contract="WSADPITG.IService" address="" name="WSADPITG" />
<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />
</service>
</services>
Is it possible to add a REST endpoint to expose ONLY TestConn method? What changes in code/config?
You should separate contracts,because single service can have single behavior.Hence two services should be host in your single web.config file.
WCF REST Service
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet]
string TestConn();
}
Now the configuration file.
<system.serviceModel>
<behaviors>
<serviceBehaviors >
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false 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="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="ServiceClassNamespace.YourServiceClasImplementation" behaviorConfiguration="ServiceBehavior">
<endpoint binding="webHttpBinding" contract="ServiceClassNamespace.IService" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Pure WCF Service
[ServiceContract]
public interface IService2
{
[OperationContract]
string AddRecord();
}
Your above mentioned web.config must be appended to the existing(WCF REST) config file.
<system.serviceModel>
<behaviors>
<serviceBehaviors >
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false 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="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="ServiceClassNamespace.YourServiceClasImplementation" behaviorConfiguration="ServiceBehavior">
<endpoint binding="webHttpBinding" contract="ServiceClassNamespace.IService" behaviorConfiguration="web">
</endpoint>
</service>
<service name="WSADPITG.Service" behaviorConfiguration="ServiceBehavior">
<endpoint binding="basicHttpBinding" contract="WSADPITG.IService2" address="" name="WSADPITG" />
<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />
<host>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Consider this:
[ServiceContract]
public interface ICreditCardExtractor
{
[OperationContract]
[WebGet]
string CoolAction();
}
I've directed a new app in my IIS to the artifacts, and able to surf to files.
However, when I try to invoke the CoolAction (by browsing to http://localhost/MySvc/CreditCardExtractor.svc/CoolAction)
I get
The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
This is my web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
<!--pages controlRenderingCompatibilityVersion="4.0"/-->
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<!--added service behaviour configuration-->
<services>
<service name="WcfService1.CreditCardExtractor">
<endpoint
address=""
binding="webHttpBinding"
contract="WcfService1.ICreditCardExtractor" />
</service>
</services>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
....
</configuration>
You've defined your endpoint behavior - but you haven't applied it to the service endpoint - try to update your configuration to:
<services>
<service name="WcfService1.CreditCardExtractor">
<endpoint
address=""
behaviorConfiguration="web" -- add this line here!!
binding="webHttpBinding"
contract="WcfService1.ICreditCardExtractor" />
</service>
</services>
I keep getting the page when I browse to my svc file that metadata publishing is not turned on but I have done everything for it. Here's my web.config. What am I doing wrong?
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AlphaFrontEndSiteASP.TestsServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="AlphaFrontEndSiteASP.Services.TestsService">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MetadataBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="AlphaFrontEndSiteASP.Services.TestsService" behaviorConfiguration="MetadataBehavior">
<endpoint address="" behaviorConfiguration="AlphaFrontEndSiteASP.TestsServiceAspNetAjaxBehavior" binding="webHttpBinding" contract="AlphaFrontEndSiteASP.Services.TestsService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
</system.serviceModel>
Everything else works fine, I can make SOAP and RESTful calls w/o issue via https. But WSDL always returns blank (bad request). HTTP returns WSDL fine.
Trace log inner exception reports:
The body of the message cannot be read because it is empty.
serviceMetaData tag is set:
<serviceMetadata
httpGetEnabled="true"
policyVersion="Policy15"
httpsGetEnabled="true" />
web.Config sections
Binding:
<bindings>
<basicHttpBinding>
<binding name="soapBinding">
<security mode="None">
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="webBinding">
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
You will immediately notice security mode="None"
Via ServiceHostFactory I see the mode to transport as:
ServiceHost serviceHost = new ServiceHost(service.GetType(), baseAddresses);
if (ExposeSSL(baseAddresses[0]))
{
foreach (var endpoint in serviceHost.Description.Endpoints)
{
if (endpoint.Binding is WebHttpBinding)
{
((WebHttpBinding)endpoint.Binding).Security.Mode = WebHttpSecurityMode.Transport;
endpoint.Address = new EndpointAddress(baseAddresses[0].ToString().Replace("http", "https"));
}
if (endpoint.Binding is BasicHttpBinding)
{
((BasicHttpBinding)endpoint.Binding).Security.Mode = BasicHttpSecurityMode.Transport;
endpoint.Address = new EndpointAddress(baseAddresses[0].ToString().Replace("http", "https"));
}
}
Services configuration:
<service name="xxxx.Wcf.AdminJsonService" behaviorConfiguration="DefaultBehaviour">
<host>
<baseAddresses>
<!-- note, choose an available port-->
<add baseAddress="http://localhost:62701/json"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="jsonBehavior" bindingNamespace="https://www.xxxx/WebService4/AdminJsonService" contract="xxxx.Wcf.IAdminJsonService"/>
</service>
<service name="xxxx.Wcf.AdminXmlService" behaviorConfiguration="DefaultBehaviour">
<host>
<baseAddresses>
<!-- note, choose an available port-->
<add baseAddress="http://localhost:62701/xml"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="poxBehavior" bindingNamespace="https://www.xxx/WebService4/AdminXmlService" contract="xxxx.Wcf.IAdminXmlService"/>
</service>
<service name="xxxx.Wcf.AdminSoapService" behaviorConfiguration="DefaultBehaviour">
<!-- Service Endpoints -->
<endpoint binding="basicHttpBinding" behaviorConfiguration="soapBehavior" bindingNamespace="https://www.example.com/WebService4/AdminSoapService" contract="xxxx.Wcf.IAdminSoapService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Endpoint behaviours
<!-- SOAP -->
<behavior name="soapBehavior">
</behavior>
<!-- JSON -->
<behavior name="jsonBehavior">
<webHttp/>
</behavior>
<!-- POX -->
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Service Behaviours
<behavior name="ErrorBehaviour">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior name="DefaultBehaviour">
<NiceErrorHandler/>
<!-- 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="true"/>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata
httpGetEnabled="true"
policyVersion="Policy15"
httpsGetEnabled="true" />
</behavior>
Also have
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
Anyone have idea's why this may be occurring?
Did you try turning off one of the other endpoints? In my case WCF didn't work until I disabled one of the endpoints. It didn't matter which one I disabled. The others would work.
<services>
<service name="GTW.TrendToolService" behaviorConfiguration="MyServiceBehavior">
<!--<endpoint name="rest" address="" binding="webHttpBinding" contract="TT.ITrendtoolService" behaviorConfiguration="restBehavior"/>-->
<endpoint name="json" address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="GTW.IAqvService" />
<endpoint name="xml" address="xml" binding="webHttpBinding" behaviorConfiguration="restBehavior" contract="GTW.IAqvService" />
<!--<endpoint name="mex" address="mex" binding="mexHttpBinding" contract="GTW.IAqvService" />
<endpoint name="soap" address="soap" binding="basicHttpBinding" contract="GTW.IAqvService" />-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restBehavior">
<webHttp />
</behavior>
<behavior name="jsonBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
I believe your issue is going to be related to your service behaviors section. Specifically you told .net to publish your WSDL in HTTP but not HTTPS. Try the following
<behavior name="DefaultBehaviour">
<NiceErrorHandler/>
<!-- 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="true"/>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata
httpGetEnabled="true"
httpsGetEnabled="true"
policyVersion="Policy15"
httpsGetEnabled="true" />
</behavior>
Note the extra line in the serviceMetadata referring to httpsGet as opposed to http.
I will assume that https is enabled on both the bindings and in your application given that you can see the http WSDL rather than some mumble jumbo about not being able to find bindings or something...
When you are doing the Transport encryption you have to add the s to your base address protocol ex: < add baseAddress="https://localhost:62701/xml"/> or < add baseAddress="http://localhost:62701/json"/>