Demystifying The Code

REST in WCF – Part VIII (HI-REST – Implementing Delete)

In Thursday’s post (Part VII), I illustrated how to implement insert/update functionality in a HI-REST service operation.  In this post, I will illustrate implementing a delete.  Unlike the previous post, there is little debate how to implement a RESTful delete.  Further, the lessons we learned in the previous few posts will make implementing the delete trivial.  I’m going to start motoring through…

 

The Service Contract

[OperationContract]
[WebInvoke(Method = "DELETE",
           UriTemplate = "product/{productName}")]
void DeleteProduct(string productName);

You will notice that again, I am decorating my operation contract with the WebInvokeAttribute.  Remember that this is the attribute that allows me to coerce the HTTP verb to any verb but GET (actually you can use WebInvoke for GETs, as well).  All you need to do is set the Method parameter to the HTTP Verb you want.  In this case, it is DELETE.

The next thing you will notice is that there is no RequestFormat or ResponseFormat set here.  We are neither passing any payload or returning anything.  The last thing to notice is that we are again passing in a UriTemplate.  Requests with URIs that match this template (and HTTP Verbs that match the verb set in this method) will be routed to this operation.  The UriTemplate allows you to declare variables by surrounding them with curly braces.  If they are named appropriately, the values will be passed to the appropriate parameter of the service operation.  There are more details about UriTemplates in Part V of this series.

 

The Uniform Interface

You may have heard the term ‘Uniform Interface’ with regards to REST.  If you think of a typical RPC API, there are endless method names possible: GetProducts, GetProductsAll, GetMyProducts, DeleteProducts, DeleteProduct, DeleteMyProduct, etc.  With REST, the API is defined by the HTTP verbs, typically GET, PUT, DELETE and POST.  The scoping is taken care of by the URI.  What does that mean?  Take, for example, our DeleteProduct method in an RPC API.  It may take in a product ID as a parameter.  The signature might look something like this: void DeleteProduct(int productID).  The scope of what is deleted is the parameter productID.  With our RESTful API, the scope of what is deleted is part of the URI.  In the case of our delete, it is defined in the segment of the URI containing our productName variable.  In the uniform interface, the intent of what we want to do is the verb, while the scope is found in the URI.

 

The Implementation

public void DeleteProduct(string productName)
{
    WebOperationContext ctx = WebOperationContext.Current;

    try
    {
        using (CatalogDataContext catalog = new CatalogDataContext())
        {
            Product product = catalog.Products.SingleOrDefault(p => p.ProductName == productName);
            if (product == null)
            {
                ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound;
                return;
            }

            catalog.Products.DeleteOnSubmit(product);
            catalog.SubmitChanges();

            ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
            return;
        }
    }
    catch
    {
        ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
        return;
    }
}

 

Most of this code is just plain vanilla LINQ to SQL.  However, you will note here that we are again setting the status code for failure and success, essentially alerting the caller to whether the delete was successful or not.

Consuming our Service with an AJAX Client

I am going to simply wire our delete functionality into our AJAX management application:

image_thumb43_thumb4

When the ‘Delete Product’ button is clicked, we simply get the name of the product to delete from the listbox.  We then create the URI, containing the product name to delete.  Lastly, we simply call into the restInvoke AJAX method I wrote and introduced in an earlier post.

function delProduct_clicked() {
    var productName = $get('productList').value;
    var proxy = new Sys.Net.WebServiceProxy();
    var url = "../RESTCatalogService.svc/product/" + productName;

    proxy.restInvoke(url,
        "DELETE",
        null,
        "delProduct_clicked",
        ProductDeletedEventHandler,
        ErrorEventHandler);
}

function ProductDeletedEventHandler(result) {
    clearUI();

    loadProducts();

    alert('Product Deleted');
}

Please see the Starter Solution for the implementations of clearUI and loadProducts, etc.  That just about does it for this example.   In future posts I will illustrate calling our HI-REST API from a Silverlight 2 client, as well as some other, more advanced topics like fully controlling our URI (i.e. getting rid of that blasted .svc from the URI).

Regards…

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!

Demystifying The Code