In the first part, we learned how to setup a ASP.NET 4.0 WCF (file-extension less) service and the basics on using jQuery’s $.getJSON() method to call a service implementing the GET method. Now, we are going to review all the HTTP methods commonly found in a RESTful api (GET, POST, PUT, and DELETE). The code below targets the project created in step 1, which I’ll update in my next post. Each HTTP methods/verb is used to describe a process in a CRUD transaction, so I tried to keep things simple by naming accordingly. Everything below was written in Visual Studio 2010 with .NET 4.0.

RESTful HTTP Methods ( GET / POST / PUT / DELETE )

Before we explore the HTTP methods, remember the following rules while building your WCF Services.

The UriTemplate can only use parameters of type string

Uri Templates are very flexible and you can build your own standard syntax for your api.
Sample Uri Templates for .svc-less function calls

[WebGet(UriTemplate = "Products/{name}")]
public Product GetProduct(string name)
// URL = "/InventoryService/Products/ProductXYZ"
[WebGet(UriTemplate = "Products/Product({name})")]
public Product GetProduct(string name)
// URL = "/InventoryService/Products/Product(ProductXYZ)"
[WebGet(UriTemplate = "Products/API.Service?Product={name}")]
public Product GetProduct(string name)
// URL = "/InventoryService/Products/API.Service?Product=ProductXYZ"

When passing multiple objects to a service, you must wrap the objects.
** Difference sending 1 object vs 2 objects **

//  Sending 1 Object (No Wrapping).
[WebInvoke(UriTemplate = "Products/API.Service?Product={productName}", Method = "POST")]
public string APIGet(string productName, Product product1)
// Sending 2 Objects (Wrapping)
// Added "BodyStyle = WebMessageBodyStyle.WrappedRequest".
[WebInvoke(UriTemplate = "Products/API.Service?Product={productName}", Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest )]
public string APIGet(string productName, Product product1, Product product2)

jQuery Ajax Call (Sending 1 object vs 2 objects)

// Common Objects to use in examples below
var Product1 = {};
Product1.Name = 'Name1';
Product1.Description = 'Desc1';
Product1.Price = 1.0;
Product1.Quantity = 1;
Product1.IsDiscontinued = false;
var Product2 = {};
Product2.Name = 'Name2';
Product2.Description = 'Desc2';
Product2.Price = 2.0;
Product2.Quantity = 2;
Product2.IsDiscontinued = false;
//  Sending 1 Object (No Wrapping).
$.ajax({
    type: 'POST',
    url: '/InventoryService/Products/API.Service?Product=ProductXYZ',
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    data: JSON.stringify(Product1),  // Here we are sending the 1 object, no wrapper.
    success: function (response)
    {
        // Do Something
    }
});
// Sending 2 Objects (Wrapping)
// Here we are creating a new jsonRequest object that wraps our 2 objects that we want to send to the server.
jsonRequest = { 'product1': Product1, 'product2': Product2 };
$.ajax({
    type: 'POST',
    url: '/InventoryService/Products/API.Service?Product=ProductXYZ',
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    data: JSON.stringify(jsonRequest),  // Here we are sending a object that wraps our 2 product objects.
    success: function (response)
    {
        // Do Something
    }
})

GET / POST / PUT / DELETE WCF Services and their jQuery Ajax Calls

GET Method

Service

[WebGet(UriTemplate = "Products/{name}")]
[OperationContract]
public Product GetProduct(string name)
{
	// Get a Product
}

jQuery Call

var name = 'ProductXYZ';

$.ajax({
	type: 'GET',
	url: '/InventoryService/Products/' + name,
	contentType: 'application/json; charset=utf-8',
	dataType: 'json',
	data: '',
	success: function (response)
	{
		// Do Something
	}
});

// Alternative to $.ajax for a GET request is using $.getJSON.
$.getJSON('/InventoryService/' + name, '', function (result) { // Do Something });

This is probably the simplest service call to issue, but the amazing jQuery team made the process even easier with the getJSON() call that wraps up a ajax() GET request. Notice the svc-less call above, there’s no ugly “.svc” telling your consumers… Hay, I’m using WCF!!!

POST Method

Service

[WebGet(UriTemplate = "Products/{name}", Method = "POST")]
[OperationContract]
public Product GetProduct(string name, Product product)
{
	// Insert New Product
}

jQuery Call

var name = 'ProductXYZ';
var Product = {};
Product.Name = 'ProductXYZ';
Product.Description = 'Product XYZ Description';

$.ajax({
	type: 'POST',
	url: '/InventoryService/Products/' + name,
	contentType: 'application/json; charset=utf-8',
	dataType: 'json',
	data: JSON.stringify(Product),
	success: function (response)
	{
		// Do Something
	}
});

This has always been my go to method for sending data to a service, but according to a few RESTful people this method is only supposed to be used for inserts. I’m not really sure how “firm” this rule is, so I decided to do all Inserts and Updates with the POST method, since I almost always handle this in the same function call in my DAL. In addition to posting my Object to the service, I also include the primary key (“PK”) in the service path so I can use the IIS logs to show who touched a specific record.

PUT Method

Service

[WebInvoke(UriTemplate = "Products/{name}", Method = "PUT")]
[OperationContract]
public Product GetProduct(string name)
{
	// Update Product
}

jQuery Call

var name = 'ProductXYZ';
var Product = {};
Product.Name = 'ProductXYZ';
Product.Description = 'Product XYZ Description';

$.ajax({
	type: 'PUT',
	url: '/InventoryService/Products/' + name,
	contentType: 'application/json; charset=utf-8',
	dataType: 'json',
	data: JSON.stringify(Product),
	success: function (response)
	{
		// Do Something
	}
});

I don’t use this much, but when I do the calls look exactly the same as a POST except for the change in request type.

DELETE Method

Service

[WebGet(UriTemplate = "Products/{name}", Method = "DELETE")]
[OperationContract]
public bool GetProduct(string name)
{
	// Delete Product
}

jQuery Call

var name = 'ProductXYZ';

$.ajax({
	type: 'DELETE',
	url: '/InventoryService/Products/' + name,
	contentType: 'application/json; charset=utf-8',
	dataType: 'json',
	data: '',
	success: function (response)
	{
		// Do Something
	}
});

Since I always like “confirmation” when something has been done, I always return a boolean from my delete services. This allows me to confirm something was able to be deleted, if you expect to have various failure states you might want to consider using a string return type to provide a detailed “error” message whey the request failed (e.g. “Successfully Deleted”, “You don’t have permission.”, “Product is associated with other orders.”).