Table of Contents
- Introduction
- WCF RESTful Service- Introduction
- Look at our project TweetBL defining simple Business Functionality
- Creating a WCF RESTful Service project (for TweetBL Project's Business Functionality)
- Running the default WCF RESTful Service project (Project still has AJAX configuration for Web.config)
- Modifying and running default Tweet.WCFService.RESTful Project settings (switching from AJAX to RESTful)
- Running Tweet.WCFService.RESTful Project - the simple way!
- Building WCF RESTful Service project (for TweetBL Project's Business Functionality)
- Running the WCF RESTful Service project (now with our Business Code)
- Creating and Testing WCF RESTFul Web Service Client
- Final Thoughts
Introduction
In this article, we will be looking into creating a WCF RESTful Web Service!
I would recommend giving a quick read to this article to get a brush up on basic WCF details.
I will focus on covering WCF RESTful Service related topics in this article and will not divulge the basic WCF related details example - explaining Operation Contracts. The above linked article explains these topics.
Also here is the link for the article on WCF AJAX Web Service, written by me. AJAX Web Servcie and RESTful Web Service bear a lot of resemblance as you will see during the course of this article. I have provided the link for you to look at because both leverage Web API. I would recommend to give it a quick read before going ahead with this article, as I firmly believe it will ease things for you to understand.
That being said, if you follow this article, it should not be hard for you to grasp the concept. So, don't worry as you can read them later.
We will be using a simple business layer project called TweetBL
in this article to start things up. During the course of this article, we will expose the business functionality of TweetBL
as a WCF RESTful Web Service.
We will be focusing on churning out a WCF RESTful Web service in this article and I have tried my best to keep it as simple as one can.
Following the KISS concept: "Keep it Simple Stupid."
So let's get the ball rolling...
WCF RESTful Service - Introduction
I still maintain... Windows Communication Framework (WCF) is as interesting as the Marvel Universe! no kidding.
WCF is a framework which supports message-based communication between client and server.
WCF is highly configurable...!!
We will leverage this trait of WCF by employing WebHttp
behaviour configuration option! WebHttp
behaviour provides for XML and/or JSON serialization instead of using the traditional SOAP envelopes! WebHttp
also binds custom routes for each individual operation exposed via our service.
Needless to add, it also allows for multiple HTTP verbs mentioned below:
GET
verb: used for fetching data PUT
verb: used to update data POST
verb: used to insert data DELETE
verb: used to (you guessed it right!) delete data
In short, WebHttp
behaviour provides for the required functionality for WCF to develop a REST based web service.
Note, we will also be using WebHTTPBinding
service binding as this allows us to make the connections from a web service to service methods using the predefined behaviours.
Furthermore, WCF RESTful web service is still a style of Web API style of Web Service. This means that no WSDL (Web Service Definition Language) file will be generated for a RESTful web service.
So, we have been talking about RESTful a lot... what it actually is? Well, REpresentational State Transfer (REST) is a style of Web API web service that follows a few structural guidelines (such as Uniform Interface) when it comes to accessing, updating and retrieving data!
A few highlights of REpresentational State Transfer (REST) are:
- Uniform Interface RESTful uses specific HTTP verbs for specific actions:
GET
: translates to Read
action PUT
: translates to Update
action POST
: translates to Insert
/Create
action DELETE
: translates to well Delete
action
- RESTful Web services also prefer a specific style of URI (demonstrated in point 3 with yourService.com example) that they use to access and manage information (data/resource). RESTful prefers representing the data that they manage as resources.
- Promotes cleaner URIs Example: yourService.com/SocialNetworker/1251/Tweets instead of using a query string URI... yourService.com/GetAllTweetsForSocialNetworker?SocialNetworkerId=1251
So enough of talking...
Time to roll-up our sleeves and get started!
Look at our Project TweetBL Defining Simple Business Functionality
We will expose TweetBL projects Business Functionality as a Web Service!
The project that we will be exposing as a Web Service is a simple class library project called TweetBL
.
Project TweetBL
represents the business code that has been identified to be made available over the web as a WCF RESTful web service.
TweetBL
project has the following business functionality (methods) that will be exposed as a service.
Business functionality methods are:
- Update tweet
- Save/insert a tweet
- Delete a tweet
- Retrieve tweet by id and
- Retrieve all tweets
TweetBL
Project:
![TweetBL Project Screen-shot](/KB/WCF/898527/1.png)
Tweet.cs is simply the data class identifying all data members that we have to fetch/update/insert and delete to manage tweets. Think of Model (Data Model).
![Tweet.cs Class Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
ManageTweet.cs is the class that houses the business methods that do all the necessary processing on the Tweet data to manage and maintain it.
Note: There is a bit of housekeeping code as well because we are not using an actual database to keep things fairly simple.
![ManageTweet.cs Class Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
TweetBL
project tour is over... that is it with TweetBL
functionality... it is indeed fairly simple!
Let's start with writing a RESTful web Service for our TweetBL
project.
We shall dedicate this RESTful service to all the dedicated "Twitterati's" out there... once it is completed :P
Creating a WCF RESTful Service project (for TweetBL
Project's Business Functionality)
Now that we have had a quick trip of our TweetBL
Project, it is time to jump into some real code...
Let's us start by adding a new project called Tweet.WCFService.RESTful
. This will be our WCF RESTful Service project.
![Adding Tweet.WCFService.RESTful Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select the Empty option and nothing else.
![Adding Tweet.WCFService.RESTful Empty Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Tweet.WCFService.RESTful Project added Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The above step has created an empty ASP.NET Web Application for us!
Now, we will add a WCF RESTful Service to Tweet.WCFService.RESTful
project.
Go to add new item (on Tweet.WCFService.RESTful
project) and follow the screen-shot below:
![Tweet.WCFService.RESTful Adding New Item Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Tweet.WCFService.RESTful Added New RESTful Service Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
As soon as we add the AJAX service, a few changes were made to our project.
A few references and libraries from .NET were added to our project. We will cover a few interesting bits!
Our Web.config file has also been modified!
Our Web.config file has been modified (by default) for developing an AJAX Service but we will modify it to develop a RESTful service soon. Let us have a look at that...
![Tweet.WCFService.RESTful Web.Config AJAX Configuration Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Note*: <enableWebScript />
behaviour is used to develop a WCF AJAX Web Service. But as we are developing a RESTful web service, we will make the necessary modifications to Web.config.
Also, an <endpointBehavior>
has been added to our Tweet.WCFService.RESTful
project which will enable listening of request calls for web services.
Notice the binding used "webHttpBinding
". This allows our web service clients to communicate with our service using http GET
and POST
verbs. Note only the methods decorated with Operation Contract
attribute are exposed as services.
Along with the above changes, we are also provided with a template file for our TweetService.svc class.
![Tweet.WCFService.RESTful TweetService.svc templete file Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Here unlike: SOAP over HTTP Web Services, we do not have an interface class.
The Service Contract
and Operation Contract
attributes are directly defined on the class. Also, take a note of AspNetCompatibilityRequirements
attribute: this attribute indicates that this service integrates with the ASP.NET pipeline. Now that we have created a project and have had a quick tour of what we have been given by default to work with... let's take a step further towards building the real thing!
Running the Default WCF RESTful Service Project (Project still has AJAX Configuration for Web.config)
So in our WCF project Tweet.WCFService.RESTful
let's start things by running the default code that we got after creating the project. This can be done by right clicking on TweetService.svc and selecting view in browser!
![Tweet.WCFService.RESTful TweetService.svc view in browser Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Tweet.WCFService.RESTful TweetService.svc default service-run in browser Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Beauty! The auto generated HTML page. Now this is a Web API service so no WSDL is generated!
Of course, we have come this far and there is no harm in testing the default DoWork
method that we saw in class TweetService.svc.
To do this, all we have to do is add a new attribute to the DoWork
Method. The new attribute is WebGet
is shown below in the screen-shot.
![Tweet.WCFService.RESTful TweetService.svc WebGet attribute Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Naturally, you would want to know what WebGet
attribute does? Basically, WebGet
attribute exposes operations (decorated with it) using the GET
verb! Now our DoWork
service is directly accessible via a Web browser by typing the URI to the service (TweetService.svc in our case) followed by the method/operation name (DoWork
in our case) into the address bar.
This is what we will do next.
After adding this new attribute, again, we go right click on TweetService.svc and select view in browser.
Type in method DoWork
at the end of the path... and hit enter.
![Tweet.WCFService.RESTful TweetService.svc DoWork URI Call Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
the fruits of our labour...
![Tweet.WCFService.RESTful TweetService.svc DoWork URI Call result Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
{"d":null}
is the response that we got back by making a call to DoWork
service operation. This is in JSON format.
Calling AJAX Services is this simple!
All that we have done above is run WCF AJAX web service because remember we have not yet modified Web.config file to indicate that this is a RESTful web service.
Let us do that next!
Modifying and Running Default Tweet.WCFService.RESTful Project Settings (Switching from AJAX to RESTful)
To begin with... one of the first things that we would need to do now is define a URI for our WebGet
attribute because REST places a very high importance on clean resource URIs.
This means that REST expects us to specify a specific URI to access a specific method or a specific resource.
To accomplish this, we have to pass parameters to WebGet
attribute.
To be precise, we will be employing the UriTemplate
parameter.
Modify DoWork
Method in TweetService.svc as below:
[OperationContract]
[WebGet(UriTemplate="/DoWork")]
public void DoWork()
{
return;
}
TweetService.svc Class now..
![Tweet.WCFService.RESTful TweetService.svc DoWork URI RESTful Call result Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
UriTemplate
parameter basically allows us to pass a string
which allows us to define a template for the URI that the hosting provider (in our case Web Dev server) matches with the incoming requests!
Now we are ready to invoke the DoWork
Service method..... RESTful web service style!
Oooohh... something unexpected has happened!
![Tweet.WCFService.RESTful TweetService.svc DoWork URI RESTful Call FAIL result Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
This is a Server error: indicating that we have used "UriTemplate
" to bind a URI to a specific method but we are not allowed to do that with our current configuration! (We are still on AJAX Web Service Configuration).
Making necessary changes to Web.conf file in Tweet.WCFService.RESTful
project time to move to RESTful configuration.
Web.config current state...
![Tweet.WCFService.RESTful Web.config default with enablewebscript Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
We specifically want to switch from <enableWebScript />
to <webHttp /> <webHttp>
is a WCF behaviour which provides us with more relaxed and flexible control over the HTTP communication than what <enableWebScript>
provides us with.
Why? are we doing this switch?? Still puzzled... Well.. even <enableWebScript>
uses HTTP verbs to communicate and serialize and de-serialize data (using XML or JSON) but it does so with the help of a default automatically generated JavaScript Proxy! which has its own ways of doing things.
Whereas in RESTful we would not like to use this default JavaScipt proxy as we would like more control on HTTP verbs! we want to determine ourselves which HTTP verb should be bound to which method.. along with the URIs! that we would want to define and use. <webHttp>
allows to define these all in our WebGet
and WebInvoke
attributes.
More about this automatic generated JavaScript Proxy can be read here in WCF AJAX Web Service article (i.e., if you are curious... you can read it later.. as well.)
Making the change... in Web.config file (Tweet.WCFService.RESTful
project)
![Tweet.WCFService.RESTful Web.config with webHttp Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to run TweetService.svc DoWork
method again...
![Tweet.WCFService.RESTful TweetService.svc with webHttp Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Tweet.WCFService.RESTful TweetService.svc DoWork return NULL with webHttp Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
...and DoWork
executes with no problems. Needless to add, the DoWork
method has a void
return type and hence the executing DoWork
method gives us nothing back to display.
The UriTemplate
parameter helps the server (in our case Web Dev) determine how the incoming request should be processed! It helps to deduce which service method should respond to which specific incoming request.
Let us change the UriTemplate
parameter for DoWork
method from /DoWork to /GetSomethingDone...
This will demonstrate the importance of UriTemplate
parameter! because when we will try to invoke DoWork
method using /DoWork URI, it will report Endpoint not found! as we have now changed the URI to get to DoWork
method to /GetSomethingDone
.
Changing the UriTemplate
Parameter in TweetService.svc.
![Tweet.WCFService.RESTful TweetService.svc DoWork with /GetSomethingDone UriTemplate Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Invoking DoWork
method with old UriTemplate
URI of /DoWork...
![Tweet.WCFService.RESTful TweetService.svc DoWork with /GetSomethingDone UriTemplate invoking /DoWork Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Server cannot determine how to handle this as we have mapped UriTemplate
to /GetSomethingDone.
Now let's invoke the DoWork
method using the Correct URI.
![Tweet.WCFService.RESTful TweetService.svc DoWork with /GetSomethingDone UriTemplate invoking /GetSomethingDone Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
and behold the void
of DoWork
method is back!!
With the role and importance of UriTemplate
now well understood... let us take a step forward towards exposing the real TweetBL Business methods rather than DoWork
(default method) as part of our much anticipated TweetService
!
But before going any further, let's take a small detour to make running TweetService.svc much simpler - just by using F5!
This will definitely make our life much easier and is discussed in the next section.
Running Tweet.WCFService.RESTful Project - The Simple Way!
Instead on right clicking: TweetService.svc - and selecting open in browser, we can do the following...
Set Tweet.WCFService.RESTful
Project as the Start-Up Project.
![Tweet.WCFService.RESTful TweetService.svc Set as Start up Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select TweetService.svc and Press F5.
![Tweet.WCFService.RESTful TweetService.svc Set as Start up Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
You will get the following error:
![Tweet.WCFService.RESTful TweetService.svc WCF Test Client FAILED Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Well an attempt has been made to launch the WCF Test Client but as no WSDL is generated for RESTful Services, there is no auto generated XML (WSDL) available for the WCF Test Client to tap into and help us with our services Testing... Let us fix this now; so that when we try to run Tweet.WCFService.RESTful
after selecting TweetService.svc - WCF Test Client is not employed any more to help us with our services testing!
Let's edit the Project file for Tweet.WCFService.RESTful
.
Before we can begin editing, we would need to Unload Tweet.WCFService.RESTful
project.
![Tweet.WCFService.RESTful editing Project File UNLOAD Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Once the project is unloaded, right click on the project and select "Edit Tweet.WCFService.RESTful.csproj".
![Tweet.WCFService.RESTful editing Project File Edit csproj Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Do a "Ctrl+F" for "<WebProjectProperties>
".
![Tweet.WCFService.RESTful editing Project File WebProjectProperties Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add the following element to the WebProjectProperties
for Tweet.WCFService.RESTful
project! ans SAVE the File.
<WebProjectProperties>
// Other Project Properties...
<EnableWcfTestClientForSVCDefaultValue>
false
</EnableWcfTestClientForSVCDefaultValue>
// Other Project Properties...
</WebProjectProperties>
![Tweet.WCFService.RESTful editing Project File WebProjectProperties EnableWcfTestClientForSVCDefaultValue set to false Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
After saving the changes to Tweet.WCFService.RESTful.csproj, it is time for us to reload the project...
![Tweet.WCFService.RESTful editing Project File Reload Project Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Click on YES!
![Tweet.WCFService.RESTful editing Project File Reload Project Click YES Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to set Tweet.WCFService.RESTful
project as the Start-Up Project again...
![Tweet.WCFService.RESTful editing Project File Setting as Start-Up Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select the TweetService.svc file:
![Tweet.WCFService.RESTful editing Project File Select TweetService.svc Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
In the code behind file for TweetService.svc - Press F5!
And the WCF Test Client did not pop-up! Our TweetService.svc was executed... ![Tweet.WCFService.RESTful edited Project File in TweetService.svc Press F5 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, let's move on and expose our valid TweetBL
Business Functionality as part of our RESTful Tweet Service (TweetService.svc). This is done in the next section.
Building WCF RESTful Service Project (for TweetBL Project's Business Functionality)
Time to build our real RESTful Service and remove DoWork
method! Let us tap into TweetBL
Project - ManageTweet.cs: this class has all the business code that we would need to manage a Tweet. We will expose all these methods as a RESTful Web Service.
![Tweet.WCFService.RESTful TweetService.svc with TweetBL Business Methods Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
In TweetService.svc of Tweet.WCFService.RESTful
project, we have included a reference to ManageTweet.cs of TweetBL
Project and as demonstrated in the screen-shot above, all we do is pass the call that we receive for any TweetService.svc
method to ManageTweet
class methods to do the actual work.
Simply put, all we do in our service class is call the business class to do the actual job.
Running the WCF RESTful Service Project (Now with our Business Code)
So now we are ready - to actually run our Tweet Service!
It is not going to be much different... but yes, there are a few extra steps that we will need to follow to run some of the methods! which do not implement the GET
verb (WebGet
attribute) but implement WebInvoke
attribute. Also, do not worry about the method GetTweetById
which expects an ID to be passed in the Uri... it will be very simple to test! The ones pointed out (in TweetService.svc) below:
![Tweet.WCFService.RESTful Project TweetService.svc WebInvoke Methods Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Trust me, it is good fun...
Testing GetTweets()
Method: Follow the steps highlighted in the screen-shots below:
Run the service - Select TweetService.svc and Press F5...
![Tweet.WCFService.RESTful Project TweetService.svc Running Service FAILS Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
and we get the following error!
![Tweet.WCFService.RESTful Project TweetService.svc Running Service FAILED MESSAGE Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Complete Error Message is: "Operation 'GetTweetByID' in contract 'TweetService' has a path variable named 'tweetId' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'."
Nothing DRAMATIC here! The complaint is about GetTweetByID
method that expects an int tweetId
parameter. WCF Rest cannot parse any other value other than strings in the UriTemplate! path.
The offending method(s) well the DeleteTweet
method will also offend WCF once we sort GetTweetById!
It is better to sort them out right now!
The method(s):
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetById Method Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Tweet.WCFService.RESTful Project TweetService.svc DeleteTweet Method Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
All we have to do is change int tweetId
parameter of GetTweetByID
method and int deleteTweetId
parameter of DeleteTweet
method to string
s and make the necessary data conversions in our GetTweetByID
method and DeleteTweet
method for tweetId
and deleteTweetId
parameters... converting them to int
from string
before passing them onto corresponding TweetBL
methods.
Making the proposed changes -
GetTweetByID
method:
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetById Modified Method Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
DeleteTweet
method:
![Tweet.WCFService.RESTful Project TweetService.svc DeleteTweet Modified Method Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Finally, we are back on track...
Now let's give testing TweetService.svc methods a second go!
Testing GetTweets()
Method: (Note* GetTweetByID
and DeleteTweet
methods have been fixed!) Follow the steps highlighted in the screen-shots below:
Run the service - Select TweetService.svc and Press F5...
![Tweet.WCFService.RESTful Project TweetService.svc Running Service Will Pass Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Type the method name GetTweets
:
![Tweet.WCFService.RESTful Project TweetService.svc GetTweets Method Call Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
GetTweets
method result (unformatted):
![Tweet.WCFService.RESTful Project TweetService.svc GetTweets Method unformatted result Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Notice k__BackingField
appended to each of our Tweet
property... this is because we have not marked our Tweet
Class (TweetBL
Project) with DataContract
attribute and its fields with the DataMember
attribute.
![TweetBL Project Tweet.cs DataMember Attribute Missing Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Quick refresher: Data Contracts defines the type and the format of data that will be sent out and received by the web service operations. Data Member attribute is applied to the fields of the DataContract
class that are to be serialized.
I have described a fair bit about WCF contracts in one of my previous articles, the relevant section can be found here.
Applying the attributes to Tweet.cs:
![TweetBL Project Tweet.cs DataMember Attribute Added Serialization Namespace missing Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Ouch! The red squiggly lines.. ahh.. This just indicates that you do not have reference to the "Serialization
" assembly in your TweetBL
Project!
namespace TweetBL
{
using System;
using System.Runtime.Serialization;
.... remaining code...
Let us quickly add reference to "Serialization
" assembly:
![TweetBL Project Tweet.cs Serilaization reference-1 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetBL Project Tweet.cs Serilaization reference-2 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
and the world is a happy place again...
![TweetBL Project Tweet.cs Serilaization reference-3 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Running TweetService.svc again... we get the following result: k__BackingField
is no longer appended.
![Tweet.WCFService.RESTful Project TweetService.svc GetTweets Method formatted result Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Let's run GetTweetByID()
method. This method is decorated with WebGet
attribute, but it also expects a Parameter! of type string! to be passed in as well... sweet...
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetById Method Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Running the TweetService.svc and invoking GetTweetByID
method without passing the required string
parameter will yield the following result of Endpoint not found:
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetByID Method No Param 1 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
We got the above result because WCF tried its best to match the requested URI and it failed to locate a matching method. As for GetTweetByID
method, the URI states a required string! [WebGet(UriTemplate = "/Tweet/{tweetId}")]
.
Running the TweetService.svc and invoking GetTweetByID
method with just passing the /Tweet will yield the following result of Method not allowed:
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetByID Method No Param 2 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Needless to add, none of the other methods defined in TweetService.svc have the URI of /Tweet and are decorated with WebGet
attribute!
Method UpdateTweet does have a matching URI but it is decorated with WebInvoke attribute and as we will learn shortly, the way the WebInvoke
methods are invoked is a bit different.
By default, our browser only sends WebGet
Requests!... so it fails to execute method with URI /Tweet (in this case UpdateTweet
method) because it sends the /Tweet with the HTTP request of GET
verb and UpdateTweet
method is expecting an HTTP request of PUT
verb!
Let us pass the required string Id
parameter in the URI and see the service work:
Passing 0
to GetTweetByID
method:
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetByID Method Param = 0 Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Stating the obvious here, we do not have a record with id = 0
so, null
is returned.
All we need to do is pass in a correct tweet Id (check below):
![Tweet.WCFService.RESTful Project TweetService.svc GetTweetById Method with Correct Param Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
So, this was a simple demonstration on how to run a service operation/method that is decorated with WebGet
attribute! and is expecting a string
parameter.
It's time to look at the other operations that are decorated with WebInvoke attributes TweetService.svc class...
![Tweet.WCFService.RESTful Project TweetService.svc WebInvoke Methods Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The key difference between WebGet
and WebInvoke
attribute is that it uses a POST
verb instead of a GET
verb that WebGet
uses.
Why use WebInvoke
? Well the WebInvoke
attribute exposes service operations/methods using other HTTP verbs such as POST
, PUT
, and DELETE
. These operations are meant to MODIFY a resource; therefore, the WebInvoke
attribute is used to make modifications to a resource. Note: The default option is POST
but you can change it by setting the Method Property of the WebInvoke
attribute. Demonstrated below:
[OperationContract]
[WebInvoke(Method = "PUT")]
public void PutQuestion(int id, Question question)
{
}
Another interesting thing to keep in mind is that all web browsers are optimized to cater to GET
verb requests. They cache the result of Get
requests and any-time the browser is refreshed, the results are drawn back from browser cache instead of making a trip to the Web Server.
So, for obvious reasons, now when you are performing create
, update
or delete
operations, you do not want browsers to cache the results of these operations! So, we use a different verb like Put
, Post
and others to indicate that we do not wish to cache the result of these operations and will always like to do a refresh on data once the Put
, Post
or Delete
operation has been completed successfully. It is a Win Win!
Now, moving on... if we try to run the WebInvoke
decorated operations, the way we invoked operations decorated with WebGet
attribute, we get the following result:
Method CreateTweet
- URI: /Tweets
![Tweet.WCFService.RESTful Project TweetService.svc WebInvoke Method CreateTweet Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Invocation Result:
![Tweet.WCFService.RESTful Project TweetService.svc WebInvoke Method CreateTweet run Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
We get Method not allowed message because we specified WebInvoke
attribute for CreateTweet
operation.
The question we are asking now is... How do we test our WebInvoke method CreateTweet? The simple answer is we use "Fiddler".
Fiddler: is a utility that allows us to create and monitor HTTP Get
/Put
/Post
/Delete
requests! on our machine... just what we need!
There are answers to questions that are to be found... well this question is not one of them :) thanks to Fiddler.
![Fiddler Search Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Without further ado, download and install Fiddler... (I am on Windows 8) hence I have select Fiddler 4! Please choose 2 or 4 according to the recommendations provided on the website.
![Fiddler Selected Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Running FIDDLER is simple. Locate Fiddler and run it...
![Fiddler Running Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, let's run method CreateTweet
- URI: /Tweets again using Fiddler this time!
So, we want to send a POST
request to our TweetService
!
Follow the screen-shot below: Paste in TweetService
's address and change the type to POST
!
![Fiddler Connecting to our Service Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add call to CreateTweet
's required URI: UriTemplate
for the method is /Tweets.
![Fiddler Connecting to our Service specifying the correct CreateTweet URI Screen-shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, we need to specify a valid Request Header:
This is because we would like to be upfront about the FORMAT of the data that we will be sending to the Server for processing!
Remember the CreateTweet
method expects a parameter of Type TWEET
!
![CreateTweet Parameter](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Specifying the request Header: Content-Type: application/json
, our data will be sent in json format to server!
![Request Header](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, we have come to the most important bit! specifying the message body - the data that is to be SAVED in this case! (needless to add, the format is json! as we have specified in our Request Header!)
So, we will be sending a json object to the server to SAVE as part of our call to CreateTweet
method!
{
"Id": 0,
"PostedBy": "Rahul Pawar via Fiddler",
"Text": "Saved tweet via Fiddler 4"
}
![Request Body for CreateTweet](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to click on Execute.
![Request Body for CreateTweet Execute](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Request Body for CreateTweet Execute RESULT](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![Request Body for CreateTweet Execute Response Headers](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The response of 200 indicates everything went well!
A quick call to GetTweets
method returns the newly inserted Tweet!
![GetTweets after CreateTweet Execute](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to test our UpdateTweet
method: UpdateTweet
is decorated with Web Invoke attribute that accepts a HTTP PUT
verb request.
![UpdateTweet Method](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Fire-up Fiddler...
Go to Composer... Enter the address of TweetService.svc... Select PUT
as the HTTP verb for this request...
![UpdateTweet Method Fiddler Start-up](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add call to UpdateTweet
's required URI: UriTemplate
for the method is /Tweet.
![UpdateTweet Method Fiddler UpdateTweet Method URI](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Specify the request Header: Content-Type: application/json
.
Now, we have come to the most important bit! specifying the message body - the data that is to be UPDATED via the UpdateTweet
method!
Let's Update Tweet with Id: 2 to the following:
{
"Id": 2,
"PostedBy": "UPDATED via Fiddler",
"Text": "UPDATED tweet via Fiddler"
}
![UpdateTweet Method Fiddler UpdateTweet Method Request Body](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to Execute our Update Request!
And under the Inspectors Tab - our response header of 200 indicates all has been ended well! the record has been updated!
![UpdateTweet Method Fiddler UpdateTweet Method Response Header](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
A quick call to GetTweets
method returns the newly Updated Tweet!
![GetTweets after UpdateTweet Execute](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to test our DeleteTweet
method: DeleteTweet
is decorated with Web Invoke attribute that accepts a HTTP DELETE
verb request.
![DeleteTweet Method](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Fire-up Fiddler...
Go to Composer... Enter the address of TweetService.svc... Select DELETE
as the HTTP verb for this request...
![DeleteTweet Method Fiddler Start-up](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add call to DeleteTweet
's required URI: UriTemplate
for the method is /Tweet/{deleteTweetId}.
We will be deleting Tweet with Id: 2 (the one we updated in the previous step) NOTE - in the URI, we have simply specified Tweet Id at the end! ...theURI.../2...
![DeleteTweet Method Fiddler DeleteTweet Method URI](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Note* As per HTTP specifications - with DELETE
and GET
Verbs, we are not required to send a request body! Needless to add, REST follows this specification.
Time to click Execute!
The result: we get a response of 200 - Tweet with Id: 2 has been deleted!
![DeleteTweet Method Fiddler Result](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
A quick call to GetTweets
method returns the remaining Tweet(s)!
![GetTweets after DeleteTweet Execute](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Note in the result displayed above Tweet with Id of 2 is missing because we have successfully deleted it!
With this, we have completed our quick tests for TweetService.svc and have established that it works well!
It is now time for us to create a client for our TweetService.svc. We will do this in the next section.
Creating and Testing WCF RESTFul Web Service Client
Fiddler was good for some quick unit testing. Now it's time to build our own web service client. Let us start by adding a new Console Application Project called TweetClient
which will be the client that will consume our RESTFul Tweet Web Service.
![TweetClient Project - Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project Added - Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
As WSDL is not generated for the RESTFul service, we have no luxury of default service proxy class, etc... by just introducing service reference.
We would have to do all the required serialization, de-serialization, network calls, creating data transport objects ourselves for consuming our RESTFul Tweet Web Service.. it sounds bad but hang in there as it is very simple to do so in .NET!
Let's create a folder Services and introduce a class called TweetService
that will do all the talking for our web client...
![TweetClient Project - Services Folder and TweetService Client Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Introducing the GetTweets
method!
![TweetClient Project - GetTweets missing transport object Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Ok.. so we do not have the definition for Tweet! Let us fix that first...
Let's create a folder Transports and introduce a class called Tweet
that will basically be clients Tweet
object definition...
![TweetClient Project - Transports Folder and Tweet Object Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The definition of our client side Tweet
object will not be much different to the one that we have declared in TweetBL
project!
![TweetClient Project - Transports Folder and Tweet Object Definition Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Adding the reference to Tweet
Object in our Transports folder.. all good now!
![TweetClient Project - GetTweets added transport object Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, getting back to the GetTweets
method...
In GetTweets
method, we will employ a Web Client and will request the Web Server to pass us data in JSON format.
Below is the definition for GetTweets
method - Note it has appropriate documentation for explanation:
public IList<Tweet> GetTweets()
{
var client = new WebClient();
client.Headers.Add("Accept", "application/json");
var result = client.DownloadString("http://localhost:47354/TweetService.svc/GetTweets");
var serializer = new DataContractJsonSerializer(typeof(List<Tweet>));
List<Tweet> resultObject;
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(result)))
{
resultObject = (List<Tweet>)serializer.ReadObject(stream);
}
return resultObject;
}
Screenshot of GetTweets
method:
![TweetClient Project - GetTweets Method : DataContractJsonSerializer missing- Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Oops - the red squiggly lines of death!... it is complaining about DataContractJsonSerializer
... let's add the reference and fix it!
Adding reference to: System.Runtime.Serialization
to get access to DataContractJsonSerializer
.
Note* the reference has been added in TweetClient
Project.
![TweetClient Project - Add reference to System.Runtime.Serialization.Json Take 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project - Add reference to System.Runtime.Serialization.Json Take 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project - Add reference to System.Runtime.Serialization.Json Take 3 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
and the problem has been fixed!
![TweetClient Project - Add reference to System.Runtime.Serialization.Json Take 4 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to run our GetTweets
method.
Follow the steps mentioned below:
Step 1: Set Tweet.WCFService.RESTful
as the Default Start Up Project.
Step 2: Double click on TweetService.svc in Tweet.WCFService.RESTful
.
Step 3: Go to Debug (in Menu Options) and select Start without Debugging.
Step 4: Your default browser will display the following page!
![Tweet.WCFService.RESTful- Running without Debugging Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Step 5: Jump to TweetClient
Project.
Step 6: Select TweetClient
Project, right click and follow the screen-shot below.
![TweetClient Project- Running Program Class Take 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Note* I will leave Program
Class in TweetClient
Project for you to explore on your own! as it doesn't house any article related code. All it has is a fancy GUI (you decide :)) to invoke our RESTFul Tweet Service!
After following Step 6 - the result of our labour:
![TweetClient Project- Running Program Class GUI Take 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select L (press enter) to List all Tweets - It calls our GetTweets
method:
![TweetClient Project- Running Program Class GUI Call to List all Tweets - Which wil fail Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Boom... we have an exception! The exception is thrown in GetTweets
method of TweetClient
project.
![TweetClient Project- Running Program Class GUI Call to List all Tweets FAILS: Exception Reported- Which wil fail Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Let's have a closer look at the exception.
Setting breakpoints at line 39 and 45 of TweetService
class in TweetClient
project.
![TweetClient Project- TweetService.cs with set Breakpoints lines 39 and 45 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Running the TweetClient
Project again.. to explore the condition of our application at set breakpoints...
Note* remember to type in L when the GUI pops up and press enter!
Press F10 when the execution reaches line 39 and once it is on line 45, point the cursor to variable result
on line 39... we need to look at what is stored in variable result in JSON visualizer... follow the steps below:
![TweetClient Project- TweetService.cs line 39 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
There once we select JSON visualizer... the problem becomes a bit apparent!
![TweetClient Project- TweetService.cs line 39 JSON Visulaizer Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The highlighted warning message clearly states the issue... We have requested JSON format but the web server has not complied to our request!
And because the result returned is not in JSON format, our client fails to deserialize it.
Now to fix this, we need to make a change in our Tweet.WCFService.RESTful
project..
We need to make our RESTFul TweetService.svc a bit more flexible so that it can take input from its clients about what sort of format they would like for the results to be returned in..
We can achieve this on an application level by modifying our Web.config file for Tweet.WCFService.RESTful
project...
Making the change to Web.config file!
Adding automaticFormatSelectionEnabled
will enable our service clients to specify the format of the returned data... by default, web server was returning XMLformat
and hence our TweetClient
project GetTweets
method threw exception because it requested JSON format and was operating on the premise that the server will comply with its request... well, now it will!!
![Tweet.WCFService.RESTful Project - Web.config file modified Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, here we are, let's follow the above mentioned 6 steps again to test our GetTweets
method:
And yes, remember to remove the breakpoints we added... trust me, it will all work out this time :)
Once the 6 steps are followed, we get the following result this time (after selecting L):
![TweetClient Project - GetTweets Method Result Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Volla: all the tweets on record have been returned..! Our GetTweets
method has finally delivered!
Now, moving on to the remaining methods.
Testing GetTweetByID
method...
For this GetTweetByID
method, we will request for and de-serialize XML instead of JSON.
The GetTweetByID
method:
![TweetClient Project - GetTweetById Method Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Testing the method - Now, please follow the above mentioned 6 steps again to test our GetTweetById
method
Once the program is running, follow the steps below:
Select L to get the list of all current stored tweets.
![TweetClient Project - GetTweetById Method Run Step 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Type in 1 to pull the tweet with Tweet Id of 1...
arr... more trouble...
![TweetClient Project - GetTweetById Method Result Exception Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
If we View Detail on the thrown exception:
![TweetClient Project - GetTweetById Method Result Exception detail Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
To fix this.. we need to introduce our XML Schema definition that we have defined in TweetBL
project Tweet
class.
So, in Tweet
Class in Transports folder of Tweet
client project, add the following line...
![TweetClient Project - Transport Project Tweet Client XML Definition addition Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now run the test again... the final result...
![TweetClient Project - GetTweetById Method Result Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to move onto Create Tweet
Method.
No unfortunately with WebClient
, you cannot tell which HTTP verb to use for your service operation. Web Client uses GET HTTP Verb for all of its requests.
As we desire more control when it comes to Create/Update Tweet, we would now need to employ HTTP Web Request and not Web Client as it will provide us with the ability to use other HTTP Verbs for our requests.
The CreateTweet
method:
![TweetClient Project - CreateTweet Method 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project - CreateTweet Method 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to Test CreateTweet
method
Follow the 6 steps (mentioned above) and then follow the steps mentioned below:
Type in N - for entering New Tweet...
![TweetClient Project - CreateTweet Method Test 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project - CreateTweet Method Test 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Type in L and here is the result:
![TweetClient Project - CreateTweet Method Test 3 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to Write and test out Update
method
Update
method just has one difference when compared to CreateTweet
method and that is the HTTP Verb that it uses...
Update
method requires the use of PUT
HTTP Verb.
Update
method:
![TweetClient Project - UpdateTweet Method Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Testing Update
method - Follow the 6 steps (provided above) along with the ones specified below...
Retrieving the Tweet we saved employing the CreateTweet
method...
![TweetClient Project - UpdateTweet Method Test 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select the Option E to Edit:
![TweetClient Project - UpdateTweet Method Test 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select L to List all Tweets...
![TweetClient Project - UpdateTweet Method Test 3 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The final result... updated Tweet!
![TweetClient Project - UpdateTweet Method Test 4 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Now, the last method - the DeleteTweet
method!
For Delete
, we want to send an Object that is not a Tweet
Object but has the Tweet Id
attribute in it...
Adding a New Transport Object in TweetClient
Project.. which will have the required definition of the object we desire to use for DeleteTweet
operation!
![TweetClient Project - Transport Folder Delete Tweet 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
![TweetClient Project - Transport Folder Delete Tweet 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The DeleteTweet
Method:
![TweetClient Project - Delete Tweet Method Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Time to Test the DeleteTweet
Method
Follow the above mentioned 6 steps and then follow the steps below...
Type in the id of the Tweet we added using CreateTweet
method... Select Option D to Delete it...
![TweetClient Project - Delete Tweet Test 1 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Select Y for Yes - Confirming Deletion: Also Type in L to list all tweets...
![TweetClient Project - Delete Tweet Test 2 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The fruits of our Labour.. Tweet with Id 7 has been deleted... the tweets returned does not have the tweet with id 7!
![TweetClient Project - Delete Tweet Test 3 Screen-Shot](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
and we are done!!!!
Final Thoughts
Here is a article on WCF Web Service! Also, here is the link to article on WCF Ajax Web Service!
Both articles are written by me. Both articles are a simple demo of said services demonstrating the power and simplicity of WCF.
It's time for me to sign off. Feel free to ask questions, provide feedback and everything in between as I am on the same boat with you. P.S.: The Boat is called "Burn and Learn".
History
- Version 1 submitted on 19th April 2015