REST using the WCF Web API – POST it!

Written on May 04, 2011

REST

Postings published on this series so far:

When using RESTful services you certainly don't want to GET data only but also insert them.

Using the semantics of HTTP this is done using the POST method.

The simplest implementation looks like this:

[WebInvoke(UriTemplate = "",Method = "POST")]
public HttpResponseMessage<Contact> Post(Contact contact) {
    contact = _contactRepository.Insert(contact);
    return new HttpResponseMessage<Contact>(contact);
}

Invoking this on http://localhost:2201/contacts using this request:

POST http://localhost:2201/contacts HTTP/1.1

User-Agent: Fiddler

Content-Type: application/json

Accept: application/json

Host: localhost:2201

Content-Length: 23

{"Name":"Wade Wegner"}

We get the following response:

HTTP/1.1 200 OK

Server: ASP.NET Development Server/10.0.0.0

Date: Tue, 03 May 2011 20:57:54 GMT

X-AspNet-Version: 4.0.30319

Content-Length: 30

Cache-Control: private

Content-Type: application/json; charset=utf-8

Connection: Close

{"Id":4,"Name":"Wade Wegner"}

As we've learned in the previous post we should be stateful in our response so we add the HTTP status code 201 for "Created" when everything went fine:

[WebInvoke(UriTemplate = "",Method = "POST")]
public HttpResponseMessage<Contact> Post(Contact contact) {
    contact = _contactRepository.Insert(contact);
    HttpResponseMessage<Contact> response = new HttpResponseMessage<Contact>(contact);
    response.StatusCode = HttpStatusCode.Created;
    return response;
}

Stupidly, things work not always as excepted and a client of our service may send a Contact that is null. We should state on that with an appropriate response:

[WebInvoke(UriTemplate = "",Method = "POST")]
public HttpResponseMessage<Contact> Post(Contact contact) {
    if(null == contact) {
        return new HttpResponseMessage<Contact>(HttpStatusCode.BadRequest);
    }
    contact = _contactRepository.Insert(contact);
    HttpResponseMessage<Contact> response = new HttpResponseMessage<Contact>(contact);
    response.StatusCode = HttpStatusCode.Created;
    return response;
}

The response to our POSTed null contact:

HTTP/1.1 400 Bad Request

Server: ASP.NET Development Server/10.0.0.0

Date: Tue, 03 May 2011 21:14:14 GMT

X-AspNet-Version: 4.0.30319

Cache-Control: private

Content-Length: 0

Connection: Close

But we're still not done on our way to a RESTful POST implementation: In a RESTful architecture it is a best practice to return the URI under which the newly created resource is available for further operations. In our example this would be__http://localhost/contact/4:

[WebInvoke(UriTemplate = "", Method = "POST")]
public HttpResponseMessage<Contact> Post(Contact contact, HttpRequestMessage<Contact> request) {
    if (null == contact) {
        return new HttpResponseMessage<Contact>(HttpStatusCode.BadRequest);
    }
    contact = _contactRepository.Insert(contact);
    HttpResponseMessage<Contact> response = new HttpResponseMessage<Contact>(contact);
    response.StatusCode = HttpStatusCode.Created;

    var uriBuilder = new UriBuilder(request.RequestUri);
    uriBuilder.Path = string.Format("contact/{0}", contact.Id);
    response.Headers.Location = uriBuilder.Uri;
    return response;
}

When POSTing the contact now, we'll receive the following response containing the location of our new contact:

HTTP/1.1 201 Created

Server: ASP.NET Development Server/10.0.0.0

Date: Tue, 03 May 2011 21:28:42 GMT

X-AspNet-Version: 4.0.30319

Content-Length: 30

Location: http://localhost:2201/contact/4

Cache-Control: private

Content-Type: application/json; charset=utf-8

Connection: Close

{"Id":4,"Name":"Wade Wegner"}

For now we've seen the most important facts about POSTing data in a RESTful scenario. There are some more options on POST to discover when we're playing around with PUT - but this is done in the next part of this series. Stay tuned!

Postings published on this series so far:

DotNetKicks-DE Image