Friday, September 19, 2014

Create an Ajax Web Client for OData Web API RESTful Service - HTTP-PUT JSON

In this article we'll create a web client for updating a record by sending an HTTP PUT request via Ajax to an Web API OData RESTful service using the ODataController. We'll build the full-update form by means of the Twitter Bootstrap.
To update an item, we'll send an Ajax PUT request using the OData protocol.

For this post we're using an OData Web API  built in a previous Web API ODataController tutorial. The steps for the Bootstrap's setup can be found  in this article.
The OData protocol designed for the MVC Web API using ODataControllers can be studied at the Microsoft Asp.Net site

We'll want to send an HTTP  PUT request to the OData HTTP Web API service to fully update a record. The screen to perform the Ajax PUT call will appear this way:
Ajax  OData Web API RESTful Service - HTTP-PUT JSON

First create the MVC application as an empty web site:

Import the CSS3 and javascript files  (you can see through the 2 minutes Twitter Bootstrap installing instructions here) : then, after you do so, check that you have all the required files in your app:

Take a look at the Web API ODataController class, to see the PUT( int, Note ) method that we're going to use:

You can see that the Put() action method requires a  Note object , returning an  IHttpActionResult object: a code 202 ("Accept") response if everything went right, but an error response code ("400")  if  it don't.

Ajax Web Client for OData Web API RESTful Service

Create a new html file, the web client for the OData service:

Add the references to the Twitter Bootstrap files:

Then we add an input element for selecting the KEY (int) of the item to update:

Next, we create all the DOM elements for displaying the record's details, inside  a Bootstrap panel:

This is the markup to copy-paste:

<!DOCTYPE html><html xmlns=""><head>    <title>Update</title>    <link href="Content/bootstrap.css" rel="stylesheet" />    <link href="Content/bootstrap-theme.css" rel="stylesheet" /></head><body>

    <div class="container">        <div class="jumbotron"  align="middle">            <h1>OData Web API Full Update Form</h1>            <p>Ajax HTTP GET/PUT Form to show Details & Update an item</p>            <p style="font: 900 11px Georgia;">By Carmel Shvartzman - using the Twitter Bootstrap</p>                        <p><a class="btn btn-default btn-lg" role="button">Learn more about OData Web API</a></p>        </div>

        <div class="panel panel-default">            <div class="panel-heading row">                <div class="text-muted col-xs-6">                    <h2>Message Details</h2>                </div>                <div class="text-muted col-xs-3">                    <div class="editor-label">                        ID                    </div>                    <div class="editor-field">                        <input type="number" name="ID" value="3" class="form-control" />                    </div>                </div>
            </div>            <div class="panel-body text-muted">                <div class="row">                    <div class="col-xs-6">                        <div class="editor-label">                            To                        </div>                        <div class="editor-field">                            <input type="text" name="To" class="form-control" />                        </div>                    </div>                    <div class="col-xs-6">                        <div class="editor-label">                            From                        </div>                        <div class="editor-field">                            <input type="text" name="From" class="form-control" />
                        </div>                    </div>                    <div class="col-xs-12">                        <div class="editor-label">                            Heading                        </div>                        <div class="editor-field">                            <input type="text" name="Heading" class="form-control" />
                        </div>                    </div>                    <div class="col-xs-12">                        <div class="editor-label">                            Body
                        </div>                        <div class="editor-field">                            <input type="text" name="Body" class="form-control" />
                        </div>                    </div>                    <div class="center">                        <div class="center">                            <br />                            <div class="row">                                <div class="col-lg-6">                                    <input class="btn btn-sm btn-default" value="See Message Details" />                                </div>                                <div class="col-lg-6">                                    <input class="btn btn-sm btn-default" value="Update Message" />                                </div>                            </div>                        </div>                        <br />                        <div class="alert alert-success message"></div>                        <div class="alert alert-danger error"></div>                    </div>                </div>            </div>        </div>    </div>  

After the markup, write the javascript, with the references to the jQuery and to the Bootstrap javascript files:

When the "Details" button is clicked, we send an Ajax request containing the ID of the record (inside the URI ) to be displayed :

If the response was an 200 - OK, we fill all fields; elsewhere, we display an error message:

This is the code for the script:

 <script src="Scripts/jquery-2.1.1.js"></script>    <script src="Scripts/bootstrap.js"></script>    <script>        $(function () {            $("div.message").css("display", "none");            $("div.error").css("display", "none");
            $("input.btn[value*=Details]").click(function () {
                var id = $("input[name=ID]").val();                $.ajax({                    url: "http://localhost:6954/OData/Notes(" + id + ")",                    type: "GET",                    data: id,                    dataType: "json",                    contentType: "application/json",                    beforeSend: function (data) {                        //alert(id);                    },                    success: function (data) {                        var note = data;                        $("div.error").css("display", "none");                        $("div.message").css("display", "block");                        $("div.message").text("The Message with ID = " + id + " was retrieved successfully!!!");                        $("input[name=To]").val(note.To);                        $("input[name=From]").val(note.From);                        $("input[name=Heading]").val(note.Heading);                        $("input[name=Body]").val(note.Body);                    },                    error: function (msg) {                        var oError = JSON.parse(msg.responseText);                        fnError("Error : " + oError.error.innererror.message, id);                    }                })            });
            function fnError(msg, id) {                $("div.message").css("display", "none");                $("div.error").html("The message with ID = " + id + " does not exist. Try again.");                $("div.error").css("display", "block");            }

The action method which's inside the ODataController returns the required record:

Now, we need another $.ajax method to UPDATE the just EDITED record, using the HTTP PUT verb:

This is the code for copy-paste in your project:

            $("input.btn[value*=Update]").on("click", function () {                var id = $("input.form-control[name*=ID]").val();                var to = $("input[name=To]").val();                var from = $("input[name=From]").val();                var heading = $("input[name=Heading]").val();                var body = $("input[name=Body]").val();                var data = '{"ID":"'+ id +'","To":"' + to + '","From":"' +                    from + '","Heading":"' +                    heading + '","Body":"' + body + '"}';
                $.ajax({                    url: "http://localhost:6954/OData/Notes(" + id + ")",                    type:  "PUT",                     data: data,                    contentType: "application/json",                    dataType: "json",                    success: function (data) {                        $("div.message").text('The item was successfuly updated.');                    },                    error: function (msg) {                        $("div.error").html(msg.responseText);                    }                });            });        })    </script>

Here, we create an JSON object with all the data typed by the User, and send an Ajax HTTP PUT request to the OData Web API web service. Remember: HTTP PUT is for update ALL the fields of a record; while HTTP PATCH only updates part of the fields.

Run the application: the User gets the item's details, then EDIT all or PART of the data (there's no need of changing ALL the data, because we FILL the fields with the DETAILS brought from the web service, therefore ALL fields will contain some data), and clicks the second button, for updating the record:

The Ajax request reaches the web service, which we built in a previous tutorial about setting an OData v4.0 WebAPI with full and partial updating support (HTTP PUT & HTTP PATCH) that can be found here.
This is the Put() method which handles the HTTP PUT request at the OData service:

As you see, we just Update the item, but if the Model is not valid, we concatenate all errors in a string using SelectMany(), then Select() and then the Aggregate() Linq methods.

The item was updated. But, in case of error,  for example, if we don't comply with the data annotation for the "From"  property, which requires an email , we get the following error message:

The response 400 is because there are too many characters in the "Heading" field, as stated in the Model's Data Annotations:

Therefore we got the following response from the OData service:

That's all!!!!

In this article we've seen step by step how to create a web client which fully updates a record by sending an HTTP PUT Ajax request to an WebAPI OData RESTful service implemented with an MVC ODataController. The OData Web API  is built in the previous Web API ODataController tutorial. The Bootstrap's setup can be found  in this article.
Enjoy .....

By Carmel Shvartzman

עריכה: כרמל שוורצמן