In this article, we will learn about CRUD operations in Web API using Angular JS. We will use Visual Studio 2015 to create a Web API and performs the operations. In this project, we are going to create a database and table called tbl_Subcribers
which actually contains a list of data. Here, we will use Angular JS for all of our client side operations. If you are new to Web API, please read how to retrieve the data from database using Web API here. I am going to explain the complete process in a step by step manner. I hope you will like this.
Background
Yesterday, I got a call from one of my followers. He asked me about Web API. I explained all the things I know about Web API. But he was not convinced with the information I shared on the phone. At last, he asked me to write an article about Web API in a simple manner. So, I agreed to do the same. Here, I am dedicating this article to him. I hope he can find this useful.
What is a Web API?
A Web API is a kind of a framework which makes building HTTP services easier than ever. It can be used almost everywhere including a wide range of clients, mobile devices, browsers, etc. It contains normal MVC features like Model, Controller, Actions, Routing, etc. It support all HTTP verbs like,POST,
GET
, DELETE
, PUT
.
Why Web API
Image Courtesy: blogs.msdn.com
Why Web API
Image Courtesy: forums.asp.net
Using the Code
We will create our project in Visual Studio 2015. To create a project, click File-> New-> Project. And select Web API as a template.
Web API Template
Once you have created a new project, your solution explorer will look like this:
Web API With Angular JS Solution Explorer
As I said, we are going to use Angular JS for all of our client side operations. So the next thing we need to do is, install the Angular JS from NuGet packages.
Installing Angular JS
Install Angular JS
Now, we will create a control in our project.
CRUD_in_MVC_Using_Web_API_Adding_Control
Now will create a database. Here, I am using SQL Server Management Studio With SQL Server Express.
Create Database
Below is the query to create a database.
USE [master]
GO
CREATE DATABASE [SibeeshPassion]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'SibeeshPassion', _
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\SibeeshPassion.mdf' , _
SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'SibeeshPassion_log', _
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\SibeeshPassion_log.ldf' , _
SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [SibeeshPassion] SET COMPATIBILITY_LEVEL = 120
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [SibeeshPassion].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [SibeeshPassion] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [SibeeshPassion] SET ANSI_NULLS OFF
GO
ALTER DATABASE [SibeeshPassion] SET ANSI_PADDING OFF
GO
ALTER DATABASE [SibeeshPassion] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [SibeeshPassion] SET ARITHABORT OFF
GO
ALTER DATABASE [SibeeshPassion] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [SibeeshPassion] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [SibeeshPassion] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [SibeeshPassion] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [SibeeshPassion] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [SibeeshPassion] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [SibeeshPassion] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [SibeeshPassion] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [SibeeshPassion] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [SibeeshPassion] SET DISABLE_BROKER
GO
ALTER DATABASE [SibeeshPassion] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [SibeeshPassion] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [SibeeshPassion] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [SibeeshPassion] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [SibeeshPassion] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [SibeeshPassion] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [SibeeshPassion] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [SibeeshPassion] SET RECOVERY SIMPLE
GO
ALTER DATABASE [SibeeshPassion] SET MULTI_USER
GO
ALTER DATABASE [SibeeshPassion] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [SibeeshPassion] SET DB_CHAINING OFF
GO
ALTER DATABASE [SibeeshPassion] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [SibeeshPassion] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
ALTER DATABASE [SibeeshPassion] SET DELAYED_DURABILITY = DISABLED
GO
ALTER DATABASE [SibeeshPassion] SET READ_WRITE
GO
Now, we can create a table and insert few data into it.
Create Table in Database
Below is the query to create table in database.
USE [SibeeshPassion]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_Subscribers](
[SubscriberID] [int] NOT NULL,
[MailID] [nvarchar](50) NOT NULL,
[SubscribedDate] [datetime2](7) NOT NULL,
PRIMARY KEY CLUSTERED
(
[SubscriberID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, _
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Insert Data to Table
INSERT INTO [dbo].[tbl_Subscribers] ([SubscriberID], [MailID], _
[SubscribedDate]) VALUES (1, N'sibikv4u@gmail.com', N'2015-10-30 00:00:00')
INSERT INTO [dbo].[tbl_Subscribers] ([SubscriberID], [MailID], _
[SubscribedDate]) VALUES (2, N'sibeesh.venu@gmail.com', N'2015-10-29 00:00:00')
INSERT INTO [dbo].[tbl_Subscribers] ([SubscriberID], [MailID], _
[SubscribedDate]) VALUES (3, N'ajaybhasy@gmail.com', N'2015-10-28 00:00:00')
Our database seems to be ready now. Then, we can go ahead and create an entity in our project.
Creating Entity Model
To create an entity, please follow the steps shown in the below images.
Creating Entity Model 1
Creating Entity Model 2
Creating Entity Model 3
Creating Entity Model 4
Creating Entity Model 5
Creating Entity Model 6
Now it is time to create an API controller.
Select Empty API Controller as template.
Web API Contoller With Actions
Read Operation
Now you can see some actions are already created for you by default. Cool right? Now as of now, we will concentrate only on retrieving the data. So please change the method Get
as follows:
public IEnumerable<tbl_Subscribers> Get()
{
return myEntity.tbl_Subscribers.AsEnumerable();
}
Before that, please do not forget to create an instance for your entity.
private SibeeshPassionEntities myEntity = new SibeeshPassionEntities();
And make sure you have added the needed namespaces with the model.
using System.Data.Entity;
using WebAPIAndAngular.Models;
As you can notice, we have selected Empty API Controller instead of selecting a normal controller. There are few differences between our normal controller and empty API Controller.
Controller VS Empty API Controller
A controller normally renders your views. But an API controller returns the data which is already serialized. A controller action returns JSON()
by converting the data. You can get rid of this by using API controller.
Find out more: Controller VS API Controller
Now our API is ready for action. So it is time to create an another controller and a view. Here, I am creating a normal controller with Index view.
Once the view is created, we will created three JS files in the script folder.
Angular JS Operation FIles
Now, we will start our Angular JS part. If you are new to Angular JS, I strongly recommend you to check Angular JS Basics.
Open the file Module.js and create an app.
var app;
(function () {
app = angular.module("APIModule", []);
})();
Here, APIModule
is the name of our module. Check here for more information.
Open the file Service.js and create a service as follows:
app.service("APIService", function ($http) {
this.getSubs = function () {
return $http.get("api/Subscriber")
}
});
Here, APIService
is our service name which we will call from our controller. The api/Subscriber will call the Get
method in our API controller.
Get Operation In API Controller
Now open our Controller.JS and write code as below:
app.controller('APIController', function ($scope, APIService) {
getAll();
function getAll()
{
var servCall = APIService.getSubs();
servCall.then(function (d) {
$scope.subscriber = d.data;
}, function (error) {
$log.error('Oops! Something went wrong while fetching the data.')
})
}
})
We are calling the getSubs
function which we created in our service. Once we get the data, we are assigning it to the $scope.subscriber
, so that we can use it in our view.
Now, the angular JS part for retrieving all data is done. Can we make the needed changes in the view now?
Updating View
Open the Index.cshtml view and change it as below:
@{
ViewBag.Title = "Welcome";
}
<style>
table, tr, td, th {
border: 1px solid #ccc;
padding: 10px;
margin: 10px;
}
</style>
<h2>Welcome to Sibeesh Passion's Email List</h2>
<body data-ng-app="APIModule">
<div id="tblSubs" ng-controller="APIController">
<table>
<tr>
<th>ID</th>
<th>Email ID</th>
<th>Subscribed Date</th>
</tr>
<tbody data-ng-repeat="sub in subscriber">
<tr>
<td>{{sub.SubscriberID}}</td>
<td>{{sub.MailID}}</td>
<td>{{sub.SubscribedDate}}</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/APIScripts/Module.js"></script>
<script src="~/Scripts/APIScripts/Service.js"></script>
<script src="~/Scripts/APIScripts/Controller.js"></script>
Please don’t forget to load the needed scripts. Here, we have set body
as our data-ng-app
and table
as our ng-controller
. We are looping through the data using data-ng-repeat
.
If everything is done, we can build the application and see the output.
Wep API Get All Record
So far, our READ
operation is done. Now we will move into CREATE
part.
Create Operation
First, we will concentrate on the view part as of now. Just add the below codes to your view.
<div class="form-group">
<label for="email">Sbscribe here</label>
<input type="email"
class="form-control" id="email"
placeholder="Enter email"
[required="string" ] data-ng-model="mailid" />
</div>
<button type="button" class="btn btn-default"
data-ng-click="saveSubs();">Submit</button>
This will give you an output as follows:
View Design For Create
As you can see, we are firing the function saveSubs()
in data-ng-click
. So let us see what we need to write in it.
In the Controller.js, you need to create a function as below:
$scope.saveSubs = function () {
var sub = {
MailID: $scope.mailid,
SubscribedDate: new Date()
};
var saveSubs = APIService.saveSubscriber(sub);
saveSubs.then(function (d) {
getAll();
}, function (error) {
console.log('Oops! Something went wrong while saving the data.')
})
};
Did you see that we are calling another function which is in our APIService
. So now, we need to create a function saveSubscriber
in Service.js. Shall we?
this.saveSubscriber = function (sub) {
return $http({
method: 'post',
data: sub,
url: 'api/Subscriber'
});
}
So all set, the rest is to create a function in our API Controller.
public void Post(tbl_Subscribers sub)
{
if (ModelState.IsValid)
{
myEntity.tbl_Subscribers.Add(sub);
myEntity.SaveChanges();
}
}
That’s cool, now you will be able to create data through our API with the help of Angular JS. Now, shall we move into UPDATE
operation.
Update Operation
Before going to the code part, we will make some changes in our table design. We are going to make one field (Mail ID field) editable whenever user double clicks in it. And of course, we will update the edited data to the database whenever user leaves that field. Sounds cool? Now please change the view as follows:
<div id="tblSubs" ng-controller="APIController">
<table>
<tr>
<th>ID</th>
<th>Email ID ( Double click to update)</th>
<th>Subscribed Date</th>
<th></th>
</tr>
<tbody data-ng-repeat="sub in subscriber">
<tr>
<td>{{sub.SubscriberID}}</td>
<td ng-blur="updSubscriber(sub,$event)"
ng-dblclick="makeEditable($event)">{{sub.MailID}}</td>
<td>{{sub.SubscribedDate}}</td>
</tr>
</tbody>
</table>
<div class="form-group">
<label for="email">Sbscribe here</label>
<input type="email" class="form-control" id="email"
placeholder="Enter email" [required="string" ]
data-ng-model="mailid" />
</div>
<button type="button" class="btn btn-default"
data-ng-click="saveSubs();">Submit</button>
</div>
The below is the main change we made:
<td ng-blur="updSubscriber(sub,$event)"
ng-dblclick="makeEditable($event)">{{sub.MailID}}</td>
In ng-blur
, we are calling the function updSubscriber
with parameter $event
and the current subscriber details. And in ng-dblclick
, we are calling the function makeEditable
with a parameter $event
which actually holds the UI details and current events.
Below is the code for the function in makeEditable
Controller.js.
$scope.makeEditable = function (obj) {
obj.target.setAttribute("contenteditable", true);
obj.target.focus();
};
As you can see, we are setting the attribute contenteditable
to true
using setAttribute
function. Now we will look into the function updSubscriber
.
Add a function in Controller.js:
$scope.updSubscriber = function (sub, eve) {
sub.MailID = eve.currentTarget.innerText;
var upd = APIService.updateSubscriber(sub);
upd.then(function (d) {
getAll();
}, function (error) {
console.log('Oops! Something went wrong while updating the data.')
})
};
Add a relative function in Service.js:
this.updateSubscriber = function (sub) {
return $http({
method: 'put',
data: sub,
url: 'api/Subscriber'
});
}
Now we need to add a function in our Web API controller.
public void Put(tbl_Subscribers sub)
{
if (ModelState.IsValid)
{
myEntity.Entry(sub).State = EntityState.Modified;
try
{
myEntity.SaveChanges();
}
catch (Exception)
{
throw;
}
}
}
Now you will be able to update your record. What is pending now? Yes, DELETE
operation.
Delete Operation
Make some changes in the view as follows:
<tbody data-ng-repeat="sub in subscriber">
<tr>
<td>{{sub.SubscriberID}}</td>
<td ng-blur="updSubscriber(sub,$event)"
ng-dblclick="makeEditable($event)">{{sub.MailID}}</td>
<td>{{sub.SubscribedDate}}</td>
<td>
<input type="button" id="Delete"
value="Delete" data-ng-click="dltSubscriber(sub.SubscriberID)" />
</td>
</tr>
</tbody>
Now add the new function in Controller.js:
$scope.dltSubscriber = function (subID) {
var dlt = APIService.deleteSubscriber(subID);
dlt.then(function (d) {
getAll();
}, function (error) {
console.log('Oops! Something went wrong while deleting the data.')
})
};
Create a service in Service.js now.
this.deleteSubscriber = function (subID) {
var url = 'api/Subscriber/' + subID;
return $http({
method: 'delete',
data: subID,
url: url
});
}
Now it is time to create our delete
method in Web API controller.
public void Delete(int id)
{
tbl_Subscribers dlt = myEntity.tbl_Subscribers.Find(id);
if (dlt != null)
{
try
{
myEntity.tbl_Subscribers.Remove(dlt);
myEntity.SaveChanges();
}
catch (Exception)
{
throw;
}
}
}
That is all. We did it. Now build your application and see an output as follows:
Web API With Angular JS
Happy coding!
Conclusion
Did I miss anything that you think is needed? Did you try Web API yet? Have you ever wanted to do this? Could you find this post useful? I hope you liked this article. Please share your valuable suggestions and feedback.
Your Turn. What Do You Think?
A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, Asp.Net Forum instead of commenting here. Tweet or email me a link to your question there and I’ll definitely try to help if I can.