Showing posts with label HTTP-PATCH. Show all posts
Showing posts with label HTTP-PATCH. Show all posts

Tuesday, June 19, 2018

Make a WCF RESTful Web Service with CRUD operations in 5 minutes

In this Step by step we Make a WCF RESTful Web Service with CRUD operations in 5 minutes 
   we see how to build a WCF REST web service with all CRUD operations to be Ajax called, all this   in just 5 minutes, following this simple steps :

1) Use Visual Studio templates and build an Ajax WCF web service
2) Customize it to support RESTful calls in JSON format (can also be XML)
3) Code all C.R.U.D. (Create Read Update Delete) operations


The whole code for this tutorial , can be downloaded from the following GitHub repository:
https://github.com/CarmelSoftware/WCF_RESTful_WebService
To build this service, we use a demo class which will be exposed by the REST service through HTTP calls, that you can later replace with your own EDM data model classes.
This an HTTP GET response from this RESTful WCF service :

Make a WCF RESTful Web Service with CRUD operations in 5 minutes
And this other is an HTTP PATCH request-response from this WCF REST service:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes



Make a WCF RESTful Web Service with CRUD operations in 5 minutes


The whole process for making this REST service , is as follows :

1) Use Visual Studio templates and build an Ajax WCF web service:

First build an ASP.NET Web Application using this Visual Studio template:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes



Then, add an AJAX enabled WCF web service to the project:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes

You'll get the following usable skeleton for the WCF service:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes


Take a look at the web.config file to see the WCF service configuration:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes


As you can see , there is an endpoint which wears the name of the Web service class.
The "enableWebScript " behavior sets that the service will respond to AJAX calls.


2) Customize it to support RESTful calls in JSON format (can also be XML)

First thing we do, is to change the endpoint behavior to turn it into a REST service, using the "webHttp" directive, as follows:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes

Notice that this directive replaces the "enableWebScript" one.

To make run this service, we design a demo class called "Data", which will be exposed by the REST service through HTTP calls:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes

This data will be decorated with the DataContract directive, and the properties will be DataMembers.
We also add some constructors to create some records and return them by the service.
After you have your WCF RESTful service working, you will replace this demo class with some EDM data model classes of your own.
Remember to declare "serializable" your model.



3) Code all C.R.U.D. (Create Read Update Delete) operations

Then go to the WCF class and replace the "DoWork" method with the HTTP GET method to return ALL  items:


HTTP GET :

Make a WCF RESTful Web Service with CRUD operations in 5 minutes

We specify the handle for HTTP GET requests, by using the attribute "WebGet".
Also, we stipulate the response format as JSON, since the default is XML.
And we set an UriTemplate as "/Get" , which will differentiate this method from the second GET one, which will return only one item according to the ID, which you will code as follows:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes
Notice that the return value is an array of Data objects and a single Data object, accordingly:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes

Make a WCF RESTful Web Service with CRUD operations in 5 minutes


HTTP POST :

The POST HTTP verb is used to CREATE a new item, and we define it using the WebInvoke attribute:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes

We only want to check that our REST service works, so that just return the same Data object from the request (here i'm using POSTMAN to send HTTP requests. You can also use FIDDLER for that):


Make a WCF RESTful Web Service with CRUD operations in 5 minutes

Important: the JSON object in the request's body must hold the field's data with exactly the same field names set in the DataMembers in your service: it is case-sensitive ("Id" means "Id", and no "id", got it?).

HTTP PUT:

The PUT HTTP VERB is used to update the entire item, i.e. to replace it with an updated one, and we do so by using the WebInvoke PUT option as follows:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes
The binder will give you the Date object from the request, if the names of the fields being the same as the class in a case-sensitive way, and also will give you the ID of the item to update. Check that you wrote EXACTLY the same variable name for this : "Put/{id}" == string "id" .

Test this method from POSTMAN sending an PUT request with a JSON object in the body:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes

Important: the JSON object inside the request's body must contain the field's data with exactly the same field names set in the DataMembers in your service: it is case-sensitive ("Id" means "Id", and no "id").


HTTP PATCH :

The HTTP PATCH verb is used in REST for updating just some of the object's fields:


Make a WCF RESTful Web Service with CRUD operations in 5 minutes


Again, test it using this REST call with the HTTP PATCH verb:

Make a WCF RESTful Web Service with CRUD operations in 5 minutes
HTTP DELETE :


Finally, create the method to handle HTTP DELETE requests, as follows:




Make a WCF RESTful Web Service with CRUD operations in 5 minutes




Make a WCF RESTful Web Service with CRUD operations in 5 minutes


THE END


That's all. Now you have a working WCF RESTful web service , and you can replace the Data model with your own.


      by Carmel Schvartzman


כתב: כרמל שוורצמן


Sunday, March 8, 2015

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API

In this article we explain step by step How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API,  to enable Create, Read, Update and Delete (C.R.U.D.) operations using a web service. Also we see how to add this SPA to an MVC Asp.Net C# application. In this post we'll develop from scratch in 30 minutes an entire AngularJS SPA (Single Page App) Application that sends HTTP GET, POST, PATCH and DELETE Ajax Requests to a REST OData Web API.
Our SPA will also be using the responsive Twitter Bootstrap CSS3 styles.
The whole source code for this SPA can be found in the following GitHub repository:

https://github.com/CarmelSoftware/OrchidsSPA

We'll design a unique and single main HTML file (the SPA itself, loading 4 different HTML templates , each one of them corresponding to each one of the CRUD operations)
In this tutorial , we see how to create an AngularJS SPA and, if you want to insert it to an MVC application, just drag and drop the files inside some directory in your MVC. 
This tutorial is a standalone, and allows you to design a SPA in 30 minutes,  copying-pasting code blocks to your own app as you move forward learning. But if you wish to learn AngularJS from 0,  you can take a look at the Tutorials for Absolute Beginners at The AngularJS Club starting at  Lesson #1   .                       

This is a snapshot of the SPA AngularJS that we'll develop from scratch here, in 30 minutes  :

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API




How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API in an MVC App


As you move forward through this Tutorial, you will find the source code to copy-paste to your project, beside every snapshot. That will allow you to go ahead faster.  However,  you can download the complete AngularJS SPA from this GitHub repository, packed all together in a single ZIP file:

https://github.com/CarmelSoftware/OrchidsSPA/archive/master.zip

If you already have an MVC application working, create a folder named "AngularJS", and keep using it as your root directory while creating all the files in this tutorial. We'll focus here in developing the SPA, therefore just copy it inside that folder in your MVC.
We'll use CDN(content delivery network),  to add the references for javascripts and styles,  instead of downloading the files to the project:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API       1



As you see, we add 2 AngularJS scripts, and 2 Bootstrap CSS3 files. Also, we create directories for "Content" and "Controllers".
(copy-paste the source code):
<!doctype html>
<html data-ng-app="OrchidsApp">
<head>
    <title>AngularJS SPA App
    </title>
    <link href="Contents/Style.css" rel="stylesheet" />
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"  />
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"  />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular-route.js"></script>
    <script src="/App/Controllers/SPAControllers.js" type="text/javascript"></script>
</head>

Next, copy-paste the CSS3 style to your style.css (placed at the "Contents" folder inside your root directory) file, which we'll be using besides the Bootstrap:
body {background:rgba(255, 238, 238, 0.5);
}
img {width:99%;height:99%;
}
.select
{
width:100px;
padding:5px 5px 5px 25px;
margin:10px 15px 15px 25px;
font:900 12px Comic Sans MS;
opacity:0.9;
background:#f0f0f0;    
border:5px solid #ddd;    
border-radius: 10px;
box-shadow:10px 10px 2px #c0c0c0;
}
.centered
{
 text-align:center;   
}
.div-table{
  display:table;         
  width:auto;         
  background-color:#eee;
  border-spacing:5px; 
}
.div-table-row{
  display:table-row;
  width:auto;
  clear:both;
}
.div-cell-left{
  float:left; 
  display:table-cell;         
  width:33%;
  height:200px;         
  padding:5px 5px 5px 5px;
}
.div-cell-center{
  float:left; 
  display:table-cell;         
  width:56%; 
  height:200px;         
  padding:5px 5px 5px 5px;
}
.div-cell-right{
  float:left; 
  display:table-cell;         
  width:10%; 
  height:200px;         
  padding:5px 5px 5px 5px;
}
.msg {
font:900 Comic Sans MS;
color:#1b42ae;
}

We'll also add a NavBar.html file (again at the Contents folder) containing the Bootstrap NavsBar (for more about adding the Twitter Bootstrap see this Bootstrap Tutorial):
<nav class="navbar navbar-default">
    <div class="container-fluid">

        <div class="navbar-header">
           
            <a class="navbar-brand" href="/">Orchids</a>
        </div>


        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">Home <span class="sr-only">(current)</span></a></li>
                <li><a href="#/">Orchids SPA</a></li>
                <li><a href="/PDF">Create PDF</a></li>
                <li><a href="/Home">Help</a></li>
                <li><a href="/Home/About">About</a></li>

            </ul>
            <form class="navbar-form navbar-left" role="search">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="/Home">Technologies</a></li>

            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container-fluid -->
</nav>



As we said, we'll have a unique main HTML file (the SPA itself, and 4 different templates , for  each one of the CRUD operations).At it,  add a <div> element bound to an data-ng-view, and a data-ng-include to insert the NavBar HTML5 inside the web page:
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API       2





(get the source code):
<body class="container">
    <div data-ng-include="" src="'Contents/Navbar.html'"  ></div>
    <div class="jumbotron">
        <h1>Orchids SPA - AngularJS App</h1>
        
    </div>
    <div id="container">

        <div data-ng-view=""></div>

    </div>  
</body>
</html>
This <div> element will each time be replaced by AngularJS with four Template Views, according to the User's selection ("#/" , "#/add"  ,"#/edit" and "#/delete" ),  that we're designing next: a List of All Items, a template for Creating a new Item, another one for Editing, and one for Deleting it .
We'll first design the List of flowers, so create an "/App/Views/OrchidsList.html" file, and paste the following code inside it:
<div class="jumbotron" >  
    <h2>List of my Favorite Orchids</h2>
    <h4 class="msg">{{Message}}</h4>  
</div>  
<div class="jumbotron">    

        <ul  class="list-group">                
            <li data-ng-repeat="Orchid in OrchidsList" class="list-group-item">  
                <div class="div-table" >
                 <div class="div-table-row">    
                     <div class="div-cell-left">
                        <img src="http://carmelwebapi.somee.com/AngularJS/Contents/Images/{{Orchid.MainPicture}}" alt="{{Orchid.Title}}" title="{{Orchid.Title}}"  > 
                     </div> 
                     <div  class="div-cell-center">          
                        <span >{{Orchid.BlogID}}  .  {{Orchid.Title | uppercase}} <br /><br />
                            {{Orchid.Text}}   {{Orchid.DatePosted | date }}
                        </span>  
                    </div>
                     <div class="div-cell-right">
                         <a href="#/edit/{{Orchid.BlogID}}">
                            <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
                         </a>
                         
                     </div>
                  </div>
                </div>
            </li>             
        </ul> 
        <div class="panel panel-default">      
            <div class="panel-body | centered">
                <button data-ng-click="fnShowOrchids(-1)" class="btn btn-default  btn-lg" ><span class="glyphicon glyphicon-hand-left" aria-hidden="true"></span></button>
                <input type="number" data-ng-model="pageSize" max="4" min="1" value="2" class="select"/>
                <button data-ng-click="fnShowOrchids(1)" class="btn btn-default  btn-lg" ><span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span></button>
            </div> 
        </div>  
    <a href="#/add">Add your Favorite Flowers</a>
</div>

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API          3



I've remarked the more relevant code in red. The two buttons at the bottom are for Pagination of the items forward and backwards, by sending to a Controller's method a parameter "+1" or "-1" to add to the current page index. The Input element "number" is for setting the size of the page while paging, so you could state 1 - 2 - 3 etc items per page.
The AngularJS data-ng-repeat Directive is for making a loop through all items in the Flowers collection.
For a deeper understanding of using AngularJS collections and the data-ng-repeat in this Article .
We also add two link buttons to load the "Edit" and the "Delete" HTML View Templates, using the Bootstrap's Glyphicons.
These links send the ID of the selected item to the Edit or the Delete Controllers' Methods at the AngularJS Module.

Next, we're going to code the AngularJS Module, the Routing which glues the HTML Views to its Controllers, and the Controllers themselves.

Therefore, add a javascript  SPAControllers.js file inside a "/App/Controllers/" folder, with an AngularJS Module, as follows:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API          4





var oOrchidsApp = angular.module('OrchidsApp', ['ngRoute','ngResource']);

oOrchidsApp.config(['$routeProvider', function ($routeProvider) {

    $routeProvider

    .when('/',
        {
            templateUrl: "App/Views/OrchidsList.html",
            controller: "OrchidsAllCtl"
        })
    .when('/add',
        {
            templateUrl: "App/Views/OrchidsAdd.html",
            controller: "OrchidsAddCtl"
        })
     .when('/edit/:id',
        {
            templateUrl: "App/Views/OrchidsEdit.html",
            controller: "OrchidsEditCtl"
        })
    .when('/delete/:id',
        {
            templateUrl: "/App/Views/OrchidsDelete.html",
            controller: "OrchidsDeleteCtl"
        })
    .otherwise({ redirectTo: "/" });

}]);



Using an AngularJS $routeProvider , we bind each  View with the correspondent HTML Template and  Controller. Then, when the default "/" is required, the user will be faced with the "All Flowers" HTML  template. IBut if the "/add" page is required, the "OrchidsAdd" template will be displayed.
The same for the "Edit" template.
This way, this is always the same HTML web page which is browsed here. This is a SPA application: everything  is done in THE SAME url, with no reloads of the web page!!!
That's why we needed to reference the angular-route.js AngularJS javascript at the <head> of the main HTML file: to import the $routeProvider at the Module, enabling an SPA application.

We'll also need some Global variables, that is, some data that will be reused by the different Controllers all along our application, and we do not want to repeat several times all over the App:
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API       5





oOrchidsApp.value('msg', { value: '' });

oOrchidsApp.factory('GlobalSvc', [function () {

    var oFlowersPictures = ["haeckel_orchidae.jpg", "Bulbophyllum.jpg", "Cattleya.jpg", "Orchid Calypso.jpg", "Paphiopedilum_concolor.jpg", "Peristeria.jpg", "Phalaenopsis_amboinensis.jpg", "Sobralia.jpg"];
    var sURLDev = 'http://localhost:21435/WebAPI/OrchidsWebAPI/';
    var sURLProd = 'http://CARMELWEBAPI.SOMEE.COM/WebAPI/OrchidsWebAPI/';
    var bIsDevelopmentTest = false;
    var sURL = bIsDevelopmentTest ? sURLDev : sURLProd;

    return {
        getFlowers: function () { return oFlowersPictures; },
        getURL: function () { return sURL; }

    };
}]);

This "Value" variable will hold a global message which communicates between the different Templates.
That "GlobalSvc" object is an AngularJS Service created in an Factory, and holding the URLs used all over the SPA, and also the list of pictures to be displayed by the Select list that we'll insert in every View Template.
We set two URLs: one for testing purposes, and one for Deployment.

Next, we code an AngularJS Resource, that will allow us sending HTTP GET requests for some  specific ID  :
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API        6





oOrchidsApp.factory('OrchidsResource', ['GlobalSvc', '$resource',function (GlobalSvc, $resource) {
   
    return $resource(GlobalSvc.getURL() + ":id", { id: "@id" });
}]);





1 - Fetching All Items with HTTP GET:



Now we need the code for loading the View ALL Flowers Template, so add to this Controller to the Module :
oOrchidsApp.controller('OrchidsAllCtl', ['GlobalSvc', '$scope', '$http', '$log', 'msg', function (GlobalSvc, $scope, $http, $log, msg) {

    $scope.angularClass = "angular";
    $scope.OrchidsList = [];
    $scope.pageSize = 2;
    var iCurrentPage = -1; 
     

    $scope.fnShowOrchids = function (direction) {

        iCurrentPage = iCurrentPage + direction;
        iCurrentPage = iCurrentPage >= 0 ? iCurrentPage : 0;
        
        var sURL = GlobalSvc.getURL() +
            "?$skip=" +
            iCurrentPage * $scope.pageSize
            + "&$top=" +
            $scope.pageSize;


        $http.get(sURL).success(function (response) {

            $scope.OrchidsList = response;
            $log.info("OK");

        },function (err) { $log.error(err) })
        
        $scope.Message = "";
        
    }

    $scope.fnShowOrchids(1);
    $scope.Message = msg.value;

}
]);



How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API    7


At this Controller we use the Angular $http Service to send an HTTP GET request, using its get() and success() methods.  We modify the URL from the "GlobalSvc" Service,  and concatenate it according to the OData protocol, using $skip and $top for Paging,  and finally send an HTTP GET request using the $http Service. The success() method is the callback function to be called when the response is 200 (OK). In this method , we populate the list collection with the data from the response.
For a deeper insight about sending HTTP GET Ajax requests , take a look at this article about the $http HTTP GET Service.
That  "direction" argument, is for paging the results backwards ("-1") and forward ("1").
Using Angular Dependency Injection, we got three services : $scope, in order to get the scope variables; $http is for sending requests to the RESTful server; and finally, $log, for logging purposes.
What OData RESTful web service will you use to test your SPA?
If you don't have a web service of your own, you are invited to use the OData RESTful service that I  developed and deployed for you at this URL:

http://carmelwebapi.somee.com/WebAPI/OrchidsWebAPI

You are invited to freely use it. An example of using this OData REST Web API, skipping 2 items and fetching the next 3 ones:

http://carmelwebapi.somee.com/WebAPI/OrchidsWebAPI/?$skip=2&$top=3


As we said before, the $http AngularJS service provide all kinds of HTTP functionality, including sending  HTTP GET, POST, PATCH, PUT or DELETE requests. We will use both the HTTP GET,  the HTTP POST , PATCH and DELETE verbs.
Why we use HTTP PATCH and not HTTP PUT for updating?
Because PUT requires ALL fields to be send to the service, while PATCH accepts partial updates.
Official documentation for the $http service can be learned from the Angular official web site:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API          8




2 - Adding a New Item with HTTP POST:


Now we're designing the AngularJS Template View for creating a new item into the Orchids collection.
Add an "Add" Template to the Views folder, that will contain the following markup:

<div class="container">
<div class="jumbotron">
    <div class="" >    
        <h2>Add your Favorite Orchid</h2>  
    </div> 
        <form name="addOrchid" class=""
            data-ng-submit="fnAdd()">
            <input type="text" class="form-control"
            placeholder="Title"
            data-ng-model="Orchid.Title"
            required>
            <input type="text" class="form-control"
            placeholder="Text"
            data-ng-model="Orchid.Text"
            required>
            <select data-ng-model="Orchid.MainPicture"  title="Select a Picture" data-ng-options="Img for Img in Flowers" class="form-control"></select>
            <input type="submit" class="btn btn-default  btn-lg"
            value="Add"
            data-ng-disabled="addOrchid.$invalid">
            <span>{{fnShowMsg()}}</span>
        </form>
    <a href="#/">See All Flowers</a>
</div>
</div>
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API         9


As you can see, we bind the Form markup to the properties of an "Orchid" object. The submit button will trigger the fnAdd() Controller method, which we'll code inside the .js file into a new Controller , aimed to add a new item :

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API           10





(get the source code):
oOrchidsApp.controller('OrchidsAddCtl',
    ['GlobalSvc', '$http', '$scope', '$location', '$log', 'msg',
        function (GlobalSvc, $http, $scope, $location, $log, msg) {
            msg.value = "";
            $scope.Flowers = GlobalSvc.getFlowers();
            
            $scope.fnAdd = function () {

                var oFlower = { "Title": $scope.Orchid.Title, "Text": $scope.Orchid.Text, 
                               "MainPicture": $scope.Orchid.MainPicture };    

                $http({
                    url: GlobalSvc.getURL(),
                    method: "POST",
                    data: oFlower, 
                    headers: { 'Content-Type': 'application/json' }
                }).success(function (data, status, headers, config) {
                    msg.value = "New Orchid saved";
                    $scope.IsSaved = true;
                }).error(function (err) {
                     $log.error(err);
                });                
            }

            $scope.fnShowMsg = function () { return msg.value; }
            
}
]);

As before, we use the $http service to send a request, that in this case will be an HTTP POST, which will be interpreted by the REST web service as an adding request.



3 - Editing an Item with HTTP PATCH:



Next, we'll create the markup for the "Edit" View Template at our SPA. Add to the "Views" folder a new HTML file called "OrchidsEdit.html" and type the following markup:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API        11



<div class="container">
<div class="jumbotron">
    <div class="" >    
        <h2>Edit your Favorite Orchid</h2>  
    </div> 
        <form name="editOrchid" class=""
            data-ng-submit="fnEdit()">
            <input type="text" class="form-control"
            placeholder="Title"
            data-ng-model="Orchid.Title"
            required>
            <input type="text" class="form-control"
            placeholder="Text"
            data-ng-model="Orchid.Text"
            required>
            <select data-ng-model="Orchid.MainPicture"  title="Select a Picture" data-ng-options="Img for Img in Flowers" class="form-control"></select>
            <input type="submit" class="btn btn-default  btn-lg"
            value="Update"
            data-ng-disabled="editOrchid.$invalid">
            <span>{{fnShowMsg()}}</span>
        </form>
    <a href="#/">See All Flowers</a>
    
</div>
    </div>
Again as before, we bind all HTML5 elements to the "Orchid" object. Also, we have here a "select" element that allows the user to choose a picture for the post. This select will be loaded at a new Controller that you will append to the javascript Module as follows:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API          12



oOrchidsApp.controller('OrchidsEditCtl',
    ['OrchidsResource', 'GlobalSvc', '$http', '$routeParams', '$scope', '$location', '$log', 'msg',
        function (OrchidsResource, GlobalSvc, $http, $routeParams, $scope, $location, $log, msg) {

    msg.value = "";
    $scope.Flowers = GlobalSvc.getFlowers();
    $scope.Orchid = OrchidsResource.get({ id: $routeParams.id });

    $scope.fnEdit = function () {
                
        var oFlower = { "BlogId": $routeParams.id , "Title": $scope.Orchid.Title, 
                       "Text": $scope.Orchid.Text, "MainPicture": $scope.Orchid.MainPicture };
        
        $http({
            url: GlobalSvc.getURL() + $routeParams.id,
            method: "PATCH",
            data: oFlower,
            headers: { 'Content-Type': 'application/json' }

        }).success(function (data) { msg.value = "Orchid successfully updated"; }).error(function (err) { });

        
    }
    
    $scope.fnShowMsg = function () { return msg.value; }
}
]);

Here are however some new things that weren't there at the previous Controllers, and that will call your attention. For instance,  the $routeParams.id : this service will allows us to get the ID of the chosen item to be edited.
Also , the OrchidsResource's  get() method is used to send an HTTP GET request and to get the specific data for the item that we're going to edit.
Then as before, we use the $http to send this time an HTTP PATCH request. If the response is successful ("success"), we output in the "msg" value some feedback to the user. Because this "msg" variable is a Global one, it will also allows us to show a message at the List View Template (remember: this "List" View has another different $scope at all, so a variable from this "Edit" Controller will not be seen at the "List" Controller).

Save and run your SPA:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API            13




Click the "Add" link to be shown the "Add" template, which will look this way:


How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API            14



Here you will create a new item. The list of pictures is shown at this drop down list:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API          15


Save a new flower, to test how it works:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API       16


If  the web service is working properly, after a sec you should see the "New orchid saved" message  .
Now, go back to the "See all flowers" template View , and remember, since this is a SPA , we're actually located at the SAME html web page.

At the List, we should see the new created item added to the collection. By clicking the "Edit" icon, we'll edit it:
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API        17



Take a looka at the URL : it contains the ID of the item being edited. Proceed to make some editing, and click the "Update" button, thus sending an HTTP PATCH request to the OData REST service:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API      18



By now, we have added and edited product items. In case that you get no response from the web service, check at the Developer's Tools (pressing the F12) , at the "Network" tab, for the response status. If there is some error , take a look at this HTTP Error Tutorial.
If everything is OK, check for the edited item at the items List, and notice the "Msg"  displayed there.   





4 - Deleting  an Item with HTTP DELETE:



Finally, we build the support for deleting an item:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API      19





We'll add the "Delete" functionality to our SPA application,  by coding a new View template called OrchidsDelete.html as follows:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API             20




<div class="container">
<div class="jumbotron">
    <div class="" >    
        <h2>Delete this Orchid</h2>  
    </div> 
        <form name="deleteOrchid" class=""
            data-ng-submit="fnDelete()">
            <input type="text" class="form-control"
            placeholder="Title"
            data-ng-model="Orchid.Title"
            disabled>
            <input type="text" class="form-control"
            placeholder="Text"
            data-ng-model="Orchid.Text"
            disabled>
            <input  data-ng-model="Orchid.MainPicture"  
                class="form-control" 
                disabled/> 
            <input type="submit" class="btn btn-default  btn-lg"
            value="Delete"
            data-ng-disabled="fnDisable()" ><span>&nbsp;{{fnShowMsg()}}</span>
        </form>
    
    <a href="#/">See All Flowers</a>
</div>
    </div>

Notice that all fields are read-only on this View. We do not allow here to edit the item.

At the javascript file, we append a fourth Controller, for the delete functionality:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API        21




oOrchidsApp.controller('OrchidsDeleteCtl',
    ['OrchidsResource', 'GlobalSvc', '$http', '$routeParams', '$scope', '$location', '$log', 'msg',
        function (OrchidsResource, GlobalSvc, $http, $routeParams, $scope, $location, $log, msg) {

            msg.value = "";
            $scope.isDisabled = false;
            $scope.Orchid = OrchidsResource.get({ id: $routeParams.id });    

            $scope.fnDelete = function () {

                $http(
                {
                    url:  GlobalSvc.getURL() + $routeParams.id,
                    method:"DELETE"

                }
                ).success(function (response) {
                    msg.value = "Orchid successfully deleted";
                    $scope.isDisabled = true;
                }).error(function (err) {  $log.error(err); });
               
            }

            $scope.fnDisable = function () { return $scope.isDisabled;}

            $scope.fnShowMsg = function () { return msg.value; }


}]);





As you can see here,  we call the AngularJS $resource to get the data for displaying the selected item. We do this by sending an HTTP GET  request to the service, containing the ID of the item.
When the submit button is clicked, we send an HTTP DELETE request by using the Angular $http service inside the Controller  . 
The $routeParams service instantiated by Dependency Injection is for getting the ID of the item for deleting.
In addition, we add this methods: the fnDisable() one is to disable the submit button only in the case that the response has been successfully received. Therefore, the user cannot try to erase the same item twice.
And the fnShowMsg() method is to display a message to the user.
To check this functionality, go to the Main web page, and click over the Bootstrap's "delete" icon:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API         22





The Delete View will be displayed as follows:
How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API         23



Click on the "Delete" button, and wait some secs for the success message:

How to Design an AngularJS SPA with CRUD operations for OData RESTful Web API         24


The item has been erased.
Try to remember using the $log functionality in your SPA, to send to yourself messages from your AngularJS app.

That's All!!! You have built an entire SPA application, with support for full CRUD functionality,  connected to an OData RESTful Web API service, and using AngularJS Dependency Injection, Factories, Services, Resources, Controllers, Collections, data binding and Route Provider Services .

Enjoy AngularJS, and Happy Programming ....

      by Carmel Schvartzman


             



כתב: כרמל שוורצמן