Gooddogs Development Blog

WCF Series: Part #4 Adding a REST interface to your Service

Feb 13

Written by:
2/13/2011 4:42 PM  RssIcon

In Part#3, we created our WCF Service, defined a ServiceContract, wrote the Implementation code, and finally, a unit test verify that our new Service was working. Now in this section, we’ll take a look at the Configuration part of the service add a REST endpoint to our service which will allow us to use IE as our test client and make a RESTful call to our DNNService.

The Web.Config file:

When we added our DNNService to our DotNetNuke web site, Visual Studio added a section at the end of our web.config file names “system.ServiceModel”. For our DNNService example, the system.ServiceModel section looks like this

 1: <system.serviceModel>
 2: <services>
 3: <service behaviorConfiguration="DNNServiceBehavior" name="DNNService">
 4: <endpoint address="" binding="wsHttpBinding" contract="IDNNService">
 5: <identity>
 6: <dns value="localhost" />
 7: identity>
 8: endpoint>
 9: <endpoint address="mex" binding="mexHttpBinding" 
 10: contract="IMetadataExchange" />
 11: service>
 12: services>
 13: <behaviors>
 14: <serviceBehaviors>
 15: <behavior name="DNNServiceBehavior">
 16: <serviceMetadata httpGetEnabled="true" />
 17: <serviceDebug includeExceptionDetailInFaults="false" />
 18: behavior>
 19: serviceBehaviors>
 20: behaviors>
 21: system.serviceModel>

There are two major sections within the system.serviceModel tag, “service” and “behaviors”. Within the “services” section, we expect to see one “service” tag for each service we define within our web site. In our case, we defined a single service named DNNService, and you can see that tag on line 3 above. The service tag establishes the name of the servicve (“DNNService”) and the behavior that we want to apply to that service. You can see on line 3 that we’re telling WCF to apply a behavior named “DNNServiceBehavior” to our DNNService. If you look in the “behaviors” section, you’ll see a behavior with that matching name “DNNServiceBehavior” on line 15. Within that behavior tag, we’re setting some properties to tell WCF to allow clients to request meta data (line 16) and not to include details about our service when throwing exceptions (line 17). Changing line 17 to true is sometime useful when debugging a service problem, but should always be set to false for production sites.

If you remember from earlier in this series, I said you can define multiple endpoints for your service, and you can think of endpoints as ‘doors’ into your service through which clients will send/receive messages. By default, when you create a service, Visual Studio will create two endpoints for you. You can see that on lines 4 and 9 above. Endpoints have addresses, bindings and behaviors and contracts.

Endpoints:

Address: a relative address to our .svc file which we will use to access that particular endpoint

Bindings: tells WCF in what format to receive and send messages. Some examples are Http, NetTCP, MSMQ, etc. In the context of a DotNetNuke web site, you’ll almost always use one of the Http bindings.

Behaviors: behaviors allow you to modify some of the characteristics of your service such as the level of debug information to send on exceptions, and what type of security you want to apply.

Contract: you must tell WCF what contract each endpoint will implement. This allows WCF to know which functions to expose through that specific ‘door’ and what data contracts to use. So, you can create multiple endpoints and expose different data and functionality through each one. You could create an ‘admin’ endpoint to expose administration functions and sensitive data, then apply strict security behaviors to that endpoint to make it secure, then create a second endpoint that only retrieves public data and therefore has no security.

So, we have two endpoints. The first one, one line 4, is an endpoint that will use wsHttpBinding and implement the IDDNService contract. wsHttpBinding is similar to the basicHttpBinding, but provides more Web service features. It uses the HTTP transport and provides message security, as does basicHttpBinding, but it also provides transactions, reliable messaging, and WS-Addressing, either enabled by default or available through a single control setting.

basicHttpBinding and wsHttpBinding both use SOAP messages to communicate with our service.

webHttpBinding uses Http to communicate with our service.

The second endpoint (line 9) provides a metadata exchange endpoint. This endpoint will allow a client to request meta data from our service to use to generate a client proxy to talk to our service.

Adding a REST endpoint:

So, now that you understand how the config entries are used to define yrou service and endpoint, let’s add a REST endpoint. Looking at our web.config above, we’ll add a couple of lines after line 10 to define a new endpoint.

 1: <endpoint address="rest" 
 2:    binding="webHttpBinding" behaviorConfiguration="httpBehavior" 
 3:    contract="IDNNService"/>

Line 11 defines our new endpoint, sets the relative address to “rest”., so we will be able to access our REST endpoint at “/DNNService.svc/rest”. We set the binding to “webHttpBinding” because we want all traffic into and out of this endpoint to use the Http protocol, and we tell WCF that this endpoint will be implementing the IDDNService.

On line 12, we need to do one more thing, we need to set some ‘behavior’ to our endpoint, so we add a “behaviorConfiguration” property and tell it to look for an endpoint behavior named “httpBehavior”

Finally, we need to add that behavior. Add an endpoint behavior with a matching name and add the “WebHttp” property. Setting that property will again tell WCF that this endpoint will utilize the Web Programming model and that this service will be accessible by Ajax and Http calls. Add this section to the “” section.

 1: <endpointBehaviors> 
 2:    <behavior name="httpBehavior"> 
 3:       <webHttp/> 
 4:    </behavior> 
 5: </endpointBehaviors>

That’s all the changes we need to make to our web.config. Our new web.config looks like below. So, it sounded complicated :) but in reality all we had to do was add lines 11-12 and 22-26.

 1: <system.serviceModel> 
 2:   <services> 
 3:     <service behaviorConfiguration="DNNServiceBehavior" name="DNNService"> 
 4:       <endpoint address="" binding="wsHttpBinding" contract="IDNNService"> 
 5:         <identity> 
 6:           <dns value="localhost" /> 
 7:         </identity> 
 8:       </endpoint> 
 9:       <endpoint address="mex" binding="mexHttpBinding" 
 10:        contract="IMetadataExchange" /> 
 11:      <endpoint address="rest" binding="webHttpBinding" 
 12:        contract="IDNNService" behaviorConfiguration="httpBehavior"/> 
 13:   </service> 
 14:  </services> 
 15:  <behaviors> 
 16:    <serviceBehaviors> 
 17:      <behavior name="DNNServiceBehavior"> 
 18:        <serviceMetadata httpGetEnabled="true" /> 
 19:        <serviceDebug includeExceptionDetailInFaults="false" /> 
 20:      </behavior> 
 21:   </serviceBehaviors> 
 22:   <endpointBehaviors> 
 23:     <behavior name="httpBehavior"> 
 24:       <webHttp/> 
 25:     </behavior> 
 26:   </endpointBehaviors> 
 27:  </behaviors> 
 28: </system.serviceModel>

So, now we’ve made the changes to our web config and defined a new endpoint named “rest” and told WCF to expect Http traffic in and out of that endpoint and that the IDNNService contract will be implemnted through that endpoint.

Now, one last change. When using REST, every resource must have a unique address (URI). So, we need to go to our ServiceContract (IDNNSercvice.vb) and for each resource that we want to make available through our rest endpoint, we need to specify a unique URI.

IDDNService.vb:

We need to add a reference to the System.ServiceModel.Web library, so right-click on our web site and select “Add reference”

image

Browse to System.ServiceModel.Web and select it, then hit Ok.

image

Then in our IDNNService.vb file, import the System.ServiceModel.Web namespace, as shown on line 2 below.

Ok, we’re almost there!! Last thing we need to do is tell WCF what URI we want to assign to the SayHello method. We do that by adding a “WebGet” attribute to our Interface method prototype

 1: Imports System.ServiceModel 
 2: Imports System.ServiceModel.Web 
 3: 
 4: <ServiceContract()> _ 
 5: Public Interface IDNNService 
 6: 
 7: <OperationContract()> _ 
 8: <WebGet(ResponseFormat:=WebMessageFormat.Xml, UriTemplate:="hello/{s}")> _ 
 9: Function SayHello(ByVal s As String) As String 
 10: 
 11: End Interface

On line 8, we add the WebGet attribute and set the UriTemplate to “hello/{s}”. If you remember when we defined our REST endpoint in our config file, we set the relative address of our REST endpoint to “rest”. That address is relative to our .svc service file.

Now, we set relative URIs to our REST endpoint. So the URI “hello/{s}” tells WCF that if we get a request for the resource at /DNNService.svc/rest/hello/sometext, that we want to execute the SayHello function, and pass the sometext to the function as the parameter, s.

We also tell WCF how to serialize the output by setting the ResponseFormat to XML. When the results are sent back to the client, WCF will handle the serialization for you and because we set it to XML, the client will receive XML back. We could change the message format to .Json and WCF will automatically serialize the results as Json.

We save and compile. Now it’s time to test our new REST interface. We fire up IE and browse to our .svc file.

image

Wow! cool! so how did this happen? Well, remember the second endpoint that Visual Studio added to our config file for us? the meta data exchange endpoint? well, because that endpoint was defined, we get this service screen and can access the wsdl for our service. Client applications can use this to generate proxies.

But, we’re here to test out our rest interface.

Let’s try adding /rest/hello/DNN Programmers to our URL

image

NICE! it worked! We browsed to /DNNService.svc/rest/hello/DNN Programmers, which, because of our configuration told WCF that this request is looking for the door named “rest”, and then in that door, look for a matching URI in for format “hello/sometext”. Since it found a match for the SayHello function, it executed the function, passing “DNN Programmers” as the s parameter and then returned the string “Hello DNN Programmers”

Notice, we did not change our Implementation AT ALL!! we did not have to change the code of our SayHello function, we just defined a new endpoint for our service, defined the behavior and binding for that endpoint, then in our ServiceContract file, defined the unique URI for our SayHello function so WCF would be able to match an incoming request to a specific function.

Ok, so now you are all experts in WCF concepts :) In the next section, we’ll expose some Metrics from our DotNetNuke web site and build a desktop client to use that service to monitor our DotNetNuke web site.

Tags:
Categories:
Search
Privacy Statement | Terms Of Use | Copyright 2007-2009 by Gooddogs.com