POST and WCF REST Service

In the last post we created a WCF REST service to get menus and specific dish from a restaurant. This time I want to show how to submit data to the web service. The new method will enable client to book the restaurant and its response will be a boolean.

Interface first

We’ll complete the interface from the previous post by adding two new methods :

  • A method to make a booking
  • A method to get all the bookings
[OperationContract]
[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "POST", UriTemplate = "Booking")]
bool Book(Stream input);

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "Booking")]
Booking[] GetBookings();

This time we use a WebInvoke attribute instead of WebGet. That’s because we want to push data to the server, the WebGet attibute is meant to get data. Then we set the Method parameter to POST, which is the HTTP verb for creating something (use of PUT would be a good REST design too). You can notice that our methods have the same URI, it’s not a problem because they’ll be accessed from different HTTP verbs.

The code

So now we’ve defined the interface we have to implement it. A booking will be composed of a date and a number of guest property :

    public class Booking
    {
        public int NbGuest;
        public DateTime DateBooking;
    }

Pretty easy. Now we’ll take care of the implementation. Here the GetBookings methods, which is the easiest one :

        public Booking[] GetBookings()
        {
            return MenuRepository.Bookings.ToArray();
        }

For the Book method it might be a bit more complicated. We receive a stream from the web page calling the service. First we need to parse the query string using the .net framework built-in method HttpUtility. I did not implement any security in my code…so don’t be afraid if my code looks very very permissive. Parsing the query string is the most difficult part (but not that difficult!). Next step is to test if a booking already exists for the defined date and send the result to the client.

        public bool Book(Stream input)
        {
            bool result = false;
            Booking newBooking = new Booking();

            using (StreamReader sr = new StreamReader(input))
            {
                NameValueCollection qs = HttpUtility.ParseQueryString(sr.ReadToEnd());
                newBooking.DateBooking = DateTime.Parse(qs["dateBooking"].ToString());
                newBooking.NbGuest = int.Parse(qs["nbGuest"].ToString());
            }

            if (newBooking != null && !MenuRepository.Bookings.Any(bo => bo.DateBooking.Equals(newBooking.DateBooking)))
            {
                result = true;
                MenuRepository.Bookings.Add(newBooking);
            }

            return result;
        }

So it’s not so difficult isn’t it ?

Test it !

In order to test it I created a simple HTML page :


<!DOCTYPE html>

<html>
<head>
<title>Tester WCF REST</title>
</head>

<body>
<h1>GET TEST</h1>
<form action="http://localhost:57929/MyRestaurant.svc/Booking" method="get">
<input type="submit" />
</form>

<h1>POST TEST</h1>
<form action="http://localhost:57929/MyRestaurant.svc/Booking" method="POST">
<label for="date">Date</label>: <input type="date" name="dateBooking" value="" />
<label for="nbGuest">Number of guest</label>: <input type="text" name="nbGuest" value="" />
<input type="submit" />
</form>
</body>

</html>

The important thing here is to named your input tags with the name expected by the web service.