Introduction
REST (Representational State Transfer) is basically an architectural style that is based on the same principles as that of "Web". In this WCF Service tutorial, we are going to see these web principles in action. We will be using standard HTTP verbs for CRUD (Create
, Retrieve
, Update
, Delete
) operations, HTTP Content-Types, etc.
In one of my previous articles, I explained 5 simple steps to create your first RESTful web service. In part-1 of this article, we will build a RESTful web service using WCF while in the second part, we will be consuming the web service using jQuery.
Let's start by creating a WCF Service Application project using Visual Studio. Before creating actual service, let's prepare object that represents data in our application.
Following is the code for our DataContract
class i.e., "Book
".
[DataContract]
public class Book
{
[DataMember]
public int BookId { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string ISBN { get; set; }
}
For the purpose of simplicity, we are not going to write code for interacting with database. Instead we will separate code for actual CRUD operations using repository design pattern. Benefit of using repository pattern approach is that we can easily replace the implementation with actual database interaction code according to our own need.
We will create an interface "IBookRepository
" and a class "BookRepository
" as follows:
public interface IBookRepository
{
List<Book> GetAllBooks();
Book GetBookById(int id);
Book AddNewBook(Book item);
bool DeleteABook(int id);
bool UpdateABook(Book item);
}
public class BookRepository : IBookRepository
{
private List<Book> books = new List<Book>();
private int counter = 1;
public BookRepository()
{
AddNewBook(new Book { Title = "Thinking in C#", ISBN = "65674523432423" });
AddNewBook(new Book { Title = "Thinking in Java", ISBN = "34223434543423" });
AddNewBook(new Book { Title = "Beginning WCF", ISBN = "35343532423" });
}
public Book AddNewBook(Book newBook)
{
if (newBook == null)
throw new ArgumentNullException("newBook");
newBook.BookId = counter++;
books.Add(newBook);
return newBook;
}
public List<Book> GetAllBooks()
{
return books;
}
public Book GetBookById(int bookId)
{
return books.Find(b => b.BookId == bookId);
}
public bool UpdateABook(Book updatedBook)
{
if (updatedBook == null)
throw new ArgumentNullException("updatedBook");
int idx = books.FindIndex(b => b.BookId == updatedBook.BookId);
if (idx == -1)
return false;
books.RemoveAt(idx);
books.Add(updatedBook);
return true;
}
public bool DeleteABook(int bookId)
{
int idx = books.FindIndex(b => b.BookId == bookId);
if (idx == -1)
return false;
books.RemoveAll(b => b.BookId == bookId);
return true;
}
}
As we are going to perform CRUD operations using RESTful service, we must know that how these actions map to standard HTTP verbs.
Method | Action |
GET
| Getting a specific representation of a resource. In our case, get all books or get a book by a specific ID are relevant actions. |
PUT
| Create/Update a resource. Add a new book or update an existing book. |
DELETE
| Delete a resource. Delete an existing book. |
POST
| Submit data to a resource. |
Now, it's time to add WCF service contract as well as service as follows:
[ServiceContract]
public interface IBookService
{
[OperationContract]
[WebInvoke(Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Books/")]
List<Book> GetBookList();
[OperationContract]
[WebInvoke(Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "BookById/{id}")]
Book GetBookById(string id);
[OperationContract]
[WebInvoke(Method = "PUT",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "AddBook/{id}")]
string AddBook(Book book, string id);
[OperationContract]
[WebInvoke(Method = "PUT",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "UpdateBook/{id}")]
string UpdateBook(Book book, string id);
[OperationContract]
[WebInvoke(Method = "DELETE",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "DeleteBook/{id}")]
string DeleteBook(string id);
}
Service exposes methods for all CRUD operations. Major things to understand about the above code are:
WebInvoke
attribute is used to expose services using HTTP verbs like GET
, POST
, PUT
, DELETE
, etc.
Method
is the HTTP verb used for a specific action already explained above.
RequestFormat
is the request message format e.g. JSON, XML, etc.
ResponseFormat
is the response message format e.g. JSON, XML, etc.
UriTemplate
is the unique URI for each specific service operations. Service consumer only knows about unique URI defined in UriTemplate
.
Implementation code of BookService
for all operations is as follows:
public class BookService : IBookService
{
static IBookRepository repository = new BookRepository();
public List<Book> GetBookList()
{
return repository.GetAllBooks();
}
public Book GetBookById(string id)
{
return repository.GetBookById(int.Parse(id));
}
public string AddBook(Book book, string id)
{
Book newBook = repository.AddNewBook(book);
return "id=" + newBook.BookId;
}
public string UpdateBook(Book book, string id)
{
bool updated = repository.UpdateABook(book);
if (updated)
return "Book with id = " + id + " updated successfully";
else
return "Unable to update book with id = " + id;
}
public string DeleteBook(string id)
{
bool deleted = repository.DeleteABook(int.Parse(id));
if (deleted)
return "Book with id = " + id + " deleted successfully.";
else
return "Unable to delete book with id = " + id;
}
}
Configuration settings for the service given below. I have placed the complete configuration for <system.serviceModel>
.
<system.serviceModel>
<services>
<service name="RESTServiceCRUD.BookService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="RESTServiceCRUD.IBookService"
behaviorConfiguration="RESTEndpointBehavior"></endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RESTEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The above configuration is pretty similar like normal WCF service except the following:
webHttpBinding
is the binding specifically introduced for RESTful services in WCF 3.5.
endpointBehavior
is "webHttp
" for RESTful service.
We are done with implementation of all CRUD operations for a WCF RESTful service. Now, in Part-2 of this WCF tutorial series, we will consume all these operations.
Other Related Tutorials that Might Be Of Interest
CodeProject