CRUD Functionality In AngularJS And ASP.NET MVC 5 With Entity Framework Code First Approach

In this article, I will demonstrate how we can use AngularJs with ASP.net mvc. Here, we will learn about CRUD functionality by AngularJs and ASP.net mvc 5 with entity framework code first approach. We will learn some basics of asp.net identity, configure them, and very simple uses of them.

First step

If we want to use angularjs in our mvc application, first we have to download the angular.js file from https://angularjs.org/. Please make sure, you are downloading the 1.2 version of angular because we will use angularjs routing here. The 1.2 version is best for single page routing. Create an asp.net mvc web application project. Copy the angular.js file to the Scripts folder of the project. Create a folder in the project and name it Angular. Add another folder in the Angular folder and name it App. We will write all the angular codes, apps and controllers here. Then add a javascript file and name it app.js. This will be the module of all angular controllers. And then make a folder here and add a javascript file named controllers.js. Now we have to add a bundle to make a connection between the angular codes with asp.net mvc 5. To do so, open BundleConfig.cs which is in the app_start folder in the project. Add a bundle like this, 

  1. bundles.Add(new ScriptBundle("~/bundles/AngularCustom").IncludeDirectory(  
  2.                     "~/Angulars/App""*.js"true  
  3.                 ));   

The bundle name is AngularCustom and this includes all the javascript files inside the ~/Angular/App directory. Then in the _Layout.cshtml we have to add a render for this bundle at the bottom of the code. Like this,

  1. @Scripts.Render("~/bundles/AngularCustom")   

The connection between angular and asp.net mvc is ready. We can now start writing code.

Second step

We will use the default project of asp.net mvc, that visual studio provides us. Here, in this project, asp.net identity framework is pre-loaded. We will slightly customize it. In default register method, there are only two properties we can insert. Let’s add another property here for ‘Name’. To do so, let’s put a Name property just inside the IdentityModels.cs that is in the Models folder.


Enable migrations and update database. To do so, write in the Package Manager Console,

Enable-Migrations -ContextTypeName ProjectName.Models.DBContextClassName
Add-Migration 'NameFildAdded'
Update-Database

If you are new to the entity framework code first approach, please do some studying before proceeding. Now, the database is ready. By default, in the menu bar, it shows “Hello EmaiAddress”. We will put the name of the user in the menu written like “Hello NameOfUser”. To do so, let’s move to the HomeController class. Then put the [Authorize] keyword before the index action method. This keyword prevents the action method without performing log in. That means, if anyone is not logged in, he will not able to go to this method’s view. Rewrite the index method like this, 

  1. public ActionResult Index()  
  2.         {  
  3.             var emailOfUser = User.Identity.Name;  
  4.             ApplicationUser user = new ApplicationUser();  
  5.             user = db.Users.Where(p => p.UserName == emailOfUser).SingleOrDefault();  
  6.             ViewBag.Name = user.Name;  
  7.             return View();  
  8.         }   

Here, we are finding the Name of the current user by searching by his email address. We will pass this viewbag to the _LoginPartial.cshtml view. Rewrite the html like this, 

  1. <ul class="nav navbar-nav navbar-right">  
  2.         <li>  
  3.             @Html.ActionLink("Hello "+(string)ViewBag.Name +"!""Index""Manage", routeValues: null, htmlAttributes: new { title = "Manage" })  
  4.         </li>  
  5.         <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>  
  6.     </ul>   

We are casting the viewbag property into string here. Identity configuration is done here. Build and run the project to check everything is okay.

Third step

In this step, we will write some C# and angular codes. Let’s first create a model first. For that, add a class in models folder and name it Question.cs. 

  1. public class Question  
  2.     {  
  3.         public int ID { get; set; }  
  4.         public string Title { get; set; }  
  5.         public string Questions { get; set; }  
  6.         public int Vote { get; set; }  
  7.         public int View { get; set; }  
  8.         public DateTime Date { get; set; }  
  9.         public int Answer1 { get; set; }  
  10.         public string AcceptedAnswer { get; set; }  
  11.     }   

To setup a connection between this class to database, make a dbContext class and name it VirtualClassroomDBContext.cs. 

  1. public class VirtualClassroom2DBContext : DbContext  
  2.     {  
  3.         public DbSet<Question> QuestionDB { get; set; }  
  4.     }   

Now we have to write connection string in the web.config file. 

  1. <connectionStrings>  
  2.     <add name="DefaultConnection" connectionString="Server = DESKTOP-G7GTQ5B\SQLEXPRESS; Database = VirtualClassroomV2DB; user id=sa; password=cse;" providerName="System.Data.SqlClient" />  
  3.     <add name="VirtualClassroom2DBContext" connectionString="Server = DESKTOP-G7GTQ5B\SQLEXPRESS; Database = VirtualClassroomV2DB; user id=sa; password=cse;" providerName="System.Data.SqlClient" />  
  4.   </connectionStrings>   

The server is my machine server name. You have to put here your own server name as well as id and password. First things first. We will now start writing some C# code. Let’s move to HomeController and write some methods to perform crud functionality of server side. 

  1. VirtualClassroom2DBContext db = new VirtualClassroom2DBContext();[Authorize]  
  2.         public JsonResult GetQuestions()  
  3.         {  
  4.             List<Question> QuestionList = new List<Question>();  
  5.             QuestionList = db.QuestionDB.ToList();  
  6.             return Json(new { list = QuestionList }, JsonRequestBehavior.AllowGet);  
  7.         }  
  8.   
  9.         [Authorize]  
  10.         public JsonResult AddQuestion(Question question)  
  11.         {  
  12.             question.Date = DateTime.Parse(DateTime.Now.ToShortTimeString());  
  13.             db.QuestionDB.Add(question);  
  14.             db.SaveChanges();  
  15.             return Json(new { status = "Question added successfully" });  
  16.         }  
  17.   
  18.         [Authorize]  
  19.         public JsonResult GetQuestionByID(int id)  
  20.         {  
  21.             Question question = new Question();  
  22.             question = db.QuestionDB.Where(p => p.ID == id).SingleOrDefault();  
  23.             return Json(new { question = question }, JsonRequestBehavior.AllowGet);  
  24.         }  
  25.   
  26.         [Authorize]  
  27.         public JsonResult UpdateQuestion(Question question)  
  28.         {  
  29.             question.Date = DateTime.Parse(DateTime.Now.ToShortTimeString());  
  30.             db.Entry(question).State = EntityState.Modified;  
  31.             db.SaveChanges();  
  32.             return Json(new { status = "Question updated successfully" });  
  33.         }  
  34.   
  35.         [Authorize]  
  36.         public JsonResult DeleteQuestion(int id)  
  37.         {  
  38.             Question question = new Question();  
  39.             question = db.QuestionDB.Where(p => p.ID == id).SingleOrDefault();  
  40.             db.QuestionDB.Remove(question);  
  41.             db.SaveChanges();  
  42.             return Json(new { status = "Question deleted successfully" });  
  43.         }   

We have created five methods to demonstrate CRUD functionality. All the methods are returning json data with a particular status string. The code is pretty straight forward.

We will use angular route and partial views for insert, update and show the data. For that, let’s add a folder to the project and name it QuestionPartials. Then we have to add three empty html document for showing, inserting and updating the data. Like this,


Now let’s write some angular code in app.js file. 

  1. var app = angular.module("QuestionApp", ["QuestionApp.controllers""ngRoute"]);  
  2.   
  3. app.config(["$routeProvider"function ($routeProvider, $locationProvider) {  
  4.     $routeProvider          
  5.         .when("/", { templateUrl: "QuestionPartials/Questions.html", controller: "QuestionController" })  
  6.         .when("/addQuestion", { templateUrl: "QuestionPartials/AddQuestions.html", controller: "QuestionController" })  
  7.         .when("/editQuestion/:id", { templateUrl: "QuestionPartials/EditQuestion.html", controller: "QuestionEditController" })  
  8.         .when("/deleteQuestion", { templateUrl: "QuestionPartials/Questions.html", controller: "QuestionController" })  
  9.         .otherwise({ redirectTo: "/" });  
  10. }]);   

All the angular module and routing codes are written here in app.js. Please make sure that the angular route.js is linked with the document. For that, we will put the cdn link of angular routing in index.cshtml in home controller.

  1. <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-route.min.js"></script>   

In QuestionController.js, all the factory and controllers are have to be written like this, 

  1. angular.module("QuestionApp.controllers", [])  
  2. .controller("QuestionController"function ($scope, QuestionService, $routeParams) {  
  3.     $scope.message = "Message from question controller";  
  4.   
  5.     $scope.rowToDisplay = 10;  
  6.     $scope.sortColumn1 = "Date";  
  7.     $scope.reverseSort = false;  
  8.     $scope.sortData = function (column) {  
  9.         $scope.reverseSort = ($scope.sortColumn1 == column) ? !$scope.reverseSort : false;  
  10.         $scope.sortColumn1 = column;  
  11.     }  
  12.   
  13.     $scope.getSortClass = function (column) {  
  14.         if ($scope.sortColumn1 == column) {  
  15.             return $scope.reverseSort ? 'arrowDown' : 'arrowUp';  
  16.         }  
  17.         return '';  
  18.     }  
  19.     $scope.removeText = function () {  
  20.           
  21.     }  
  22.   
  23.     //Data processing with server side  
  24.     //This is the way of fetching data from post factory  
  25.     QuestionService.getQuestionFromDB().then(function (d) {  
  26.         $scope.listOfQuestion = d.data.list;  
  27.     })  
  28.   
  29.     $scope.addQuestionToDB = function () {  
  30.         QuestionService.addQuestionToDB($scope.Question);   //This is why, we used Question.title and so on in AddQuestion.html  
  31.     }  
  32.   
  33.     $scope.deleteQuestion = function (id) {  
  34.         QuestionService.deleteQuestionFromDB(id);  
  35.     }  
  36. })  
  37. .controller("QuestionEditController"function ($scope, QuestionService, $routeParams) {  
  38.     $scope.message1 = "Edit page";  
  39.     QuestionService.getQuestionByID($routeParams.id).then(function (d) {  //$routeParams.id is the id in the url  
  40.         $scope.Question = d.data.question;  
  41.     })  
  42.   
  43.     $scope.updatePlayer = function () {  
  44.         QuestionService.updateQuestionToDB($scope.Question);  
  45.     }  
  46. })  
  47. .factory("QuestionService", ["$http"function ($http, $route) {  
  48.     var fac = {};  
  49.   
  50.     fac.getQuestionFromDB = function () {  
  51.         return $http.get("/Home/GetQuestions");  
  52.     }  
  53.   
  54.     fac.addQuestionToDB = function (question) {  
  55.         return $http.post("/Home/AddQuestion", question).success(function (response) {  
  56.             alert(response.status);  
  57.             document.getElementById("title").value = "";  
  58.             document.getElementById("question").value = "";  
  59.         });  
  60.     }  
  61.   
  62.     fac.getQuestionByID = function (id) {  
  63.         return $http.get("/Home/GetQuestionByID", { params: { id: id } });  
  64.     }  
  65.   
  66.     fac.updateQuestionToDB = function (question) {  
  67.         return $http.post("/Home/UpdateQuestion", question).success(function (response) {  
  68.             alert(response.status);  
  69.         })  
  70.     }  
  71.     fac.deleteQuestionFromDB = function (id) {  
  72.         return $http.post("/Home/DeleteQuestion", { id: id }).success(function (response) {  
  73.             alert(response.status);  
  74.             // $route.reload();  
  75.         })  
  76.     }  
  77.   
  78.     return fac;  
  79. }])   

For every action, we have made separate controllers and factories. Now you have to configure the index view of home controller and the three partial views. The code is pretty straight forward. All you need is to just download the code and configure it yourself. Please make sure, the connection string has to be matched with your server.

Project Download link.