Click here to Skip to main content
15,884,425 members
Articles / Web Development / ASP.NET / ASP.NET4.0

Single Page Application Using ASP.NET MVC And jQuery With CRUD methods

Rate me:
Please Sign up or sign in to vote.
4.83/5 (3 votes)
10 Jun 2018CPOL2 min read 25.9K   51   16   3
In this article, I explain you how to implement single page application using asp.net mvc, jquery and sammy.js

Introduction

In this article, I will tell you how to create a single page application using ASP.NET MVC and jQuery. Without using Angular, React, and other third-party JavaScripts, it is difficult to achieve SPA. In this article, I will explain only controller and UI level interaction. I skipped the data access layer. If you want, please download the attachment which includes the overall code of the application.

Note - I used code first approach for CRUD operations. After downloading the project file, restore packages and change the connection string web.config and run the update-database command in Package Manager Console.

Background

Required Contents

  • ASP.NET MVC
  • JQUERY
  • Sammy.JS (for Routing)

Using the code

Create a new MVC project.

Image 1

Image 2

Add jQuery and Sammy.js reference to your layout page. Add div tag (MainContent) in which we render all the partial views.

<head>  
    <meta charset="utf-8" />  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>@ViewBag.Title - My ASP.NET Application</title>  
    @Styles.Render("~/Content/css")  
    @Scripts.Render("~/bundles/modernizr")  
    <script src="~/Scripts/jquery-1.10.2.js"></script>  
    <script src="~/Scripts/sammy-0.7.4.js"></script>  
</head>  

Create layout-routing.js file in your project which contains your application routing structure which is shown as below.

var mainContent;  
var titleContent;  
  
$(function () {  
    mainContent = $("#MainContent"); /// render partial views.  
    titleContent = $("title"); // render titles.  
});  
  
var routingApp = $.sammy("#MainContent", function () {  
    this.get("#/Student/Index", function (context) {  
        titleContent.html("Student Page");  
        $.get("/Student/Index", function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Student/Add", function (context) {  
        titleContent.html("Add Student");  
        //$("#BigLoader").modal('show'); // If you want to show loader  
        $.get("/Student/Add", function (data) {  
            //$("#BigLoader").modal('hide');  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Student/Edit", function (context) {  
        titleContent.html("Edit Student");  
        $.get("/Student/Edit", {  
            studentID: context.params.id // pass student id  
        }, function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Home/About", function (context) {  
        titleContent.html("About");  
        $.get("/Home/About", function (data) {  
            context.$element().html(data);  
        });  
    });  
  
    this.get("#/Home/Contact", function (context) {  
        titleContent.html("Contact");  
        $.get("/Home/Contact", function (data) {  
            context.$element().html(data);  
        });  
    });  
});  
  
$(function () {  
    routingApp.run("#/Student/Index"); // default routing page.  
});  
  
function IfLinkNotExist(type, path) {  
    if (!(type != null && path != null))  
        return false;  
  
    var isExist = true;  
  
    if (type.toLowerCase() == "get") {  
        if (routingApp.routes.get != undefined) {  
            $.map(routingApp.routes.get, function (item) {  
                if (item.path.toString().replace("/#", "#").replace(/\\/g, '').replace("$/", "").indexOf(path) >= 0) {  
                    isExist = false;  
                }  
            });  
        }  
    } else if (type.toLowerCase() == "post") {  
        if (routingApp.routes.post != undefined) {  
            $.map(routingApp.routes.post, function (item) {  
                if (item.path.toString().replace("/#", "#").replace(/\\/g, '').replace("$/", "").indexOf(path) >= 0) {  
                    isExist = false;  
                }  
            });  
        }  
    }  
    return isExist;  
}  

IfLinkNotExist() check if url should not repeat, after we will add dynamic url in routing list on page load.

Add layout-routing reference in _layout.cshtml page.

<script src="~/layout-routing.js"></script>  
    @*@Scripts.Render("~/bundles/jquery")*@  
    @Scripts.Render("~/bundles/bootstrap")  
    @RenderSection("scripts", required: false)  

Add a new controller ‘WelcomeController’ which has only one action ‘Index’.

namespace MvcSpaDemo.Controllers  
{  
    public class WelcomeController : Controller  
    {  
        public ActionResult Index()  
        {  
            return View();  
        }  
    }  
}

Create the View of ‘Index’ action using right-click.

In that View, attach the layout page link. (We need to render the layout page for the first time).

@{  
    ViewBag.Title = "Index";  
    Layout = "~/Views/Shared/_Layout.cshtml";  
}  
  
<h1>Welcome</h1>  

Now, create student Controller which includes student CRUD operation modules. (Add, update, delete, View).

View Students

public ActionResult Index()  
 {  
     return PartialView();  
 }  
  
 public ActionResult _Index()  
 {  
     var students = StudentData.GetStudents();  
     return PartialView(students);  
  } 

Add two Views without layout page. One for outer student contents like header, add button, etc. and another for student table.

Index.cshtml 

@{  
    Layout = null;  
}  
  
<h4>Students</h4>  
  
<div class="row">  
    <a href="#/Student/Add">Add Student</a>  
</div>  
  
<div class="row">  
    <div id="StudentDiv">  
    </div>  
</div>  
  
<script>  
    $(function () {  
        GetStudents();  
    });  
  
    function GetStudents() {  
        $.get("/Student/_Index/", function (data) {  
            $("#StudentDiv").html(data);  
        });  
    }  
  
    function DeleteStudent(studentID) {  
        if (confirm("Delete student?")) {  
            $.get("/Student/Delete/", { studentID: studentID }, function (data) {  
                GetStudents();  
            });  
        }  
    }  
</script>  

_Index.cshtml

@model IEnumerable<MvcSpaDemo.Entities.Student>  
@{  
    Layout = null;  
}  
  
<table class="table table-striped table-bordered">  
    <thead>  
        <tr>  
            <th>ID</th>  
            <th>Name</th>  
            <th>Email</th>  
            <th>Class</th>  
            <th>Action</th>  
        </tr>  
    </thead>  
    <tbody>  
        @foreach (var item in Model)  
        {  
            <tr>  
                <td>@item.StudentID</td>  
                <td>@item.FirstName @item.LastName</td>  
                <td>@item.Email</td>  
                <td>@item.Class</td>  
                <td>  
                    <a href="#/Student/Edit?id=@item.StudentID">Edit</a>  
                    <a href="javascript::;" onclick="DeleteStudent('@item.StudentID')">Delete</a>  
                </td>  
            </tr>  
        }  
    </tbody>  
</table>  

Change the default controller and action in RouteConfig.cs.

public class RouteConfig  
    {  
        public static void RegisterRoutes(RouteCollection routes)  
        {  
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  
            routes.MapRoute(  
                name: "Default",  
                url: "{controller}/{action}/{id}",  
                defaults: new { controller = "Welcome", action = "Index", id = UrlParameter.Optional }  
            );  
        }  
    }  

Run the application using F5. Do the same routing for About and Contact page also.

Image 3

Add Student asd 

Now, add "Create Student Actions" in Controller.

public ActionResult Add()  
        {  
            var student = new Student();  
            ViewBag.Status = "Add";  
            return PartialView(student);  
        }  
  
        [HttpPost]  
        public ActionResult Create(Student student)  
        {  
            StudentData.AddStudent(student);  
            return Json(true, JsonRequestBehavior.AllowGet);  
        }  

We will add the add page with dynamic routing script for create or update.

@model MvcSpaDemo.Entities.Student  
@{  
    ViewBag.Title = "Add";  
    Layout = null;  
  
    // We use same page for add and edit.  
    var urlPostString = "/Student/Create";  
    if (ViewBag.Status == "Edit")  
    {  
        urlPostString = "/Student/Update";  
    }  
}  
  
<h2>@ViewBag.Status Student</h2>  
  
<form id="frmStudent" name="frmStudent" method="post" action="#@urlPostString">  
    @Html.HiddenFor(x => x.StudentID)  
    <div class="row">  
        <div class="form-group">  
            <label for="Variables">First Name</label>  
            @Html.TextBoxFor(x => x.FirstName, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Last Name</label>  
            @Html.TextBoxFor(x => x.LastName, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Email</label>  
            @Html.TextBoxFor(x => x.Email, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <label for="Variables">Class</label>  
            @Html.TextBoxFor(x => x.Class, new { @class = "form-control square" })  
        </div>  
        <div class="form-group">  
            <input type="submit" class="btn btn-primary" value="Submit" />  
        </div>  
    </div>  
</form>  
  
<script>  
    $("#frmStudent").on("submit", function (e) {  
        debugger;  
        //if ($("#frmStudent").valid()) {  
        routingApp.runRoute('post', '#@urlPostString');  
        e.preventDefault();  
        e.stopPropagation();  
        //}  
    });  
  
    // add dynamic create or update link  
  
    debugger;  
    if (IfLinkNotExist("POST", "#@urlPostString")) {  
        routingApp.post("#@urlPostString", function (context) {  
            //$("#BigLoader").modal('show');  
            var formData = new FormData($('#frmStudent')[0]);  
            $.ajax({  
                url: '@urlPostString',  
                data: formData,  
                type: "POST",  
                contentType: false,  
                processData: false,  
                success: function (data) {  
                    //$("#BigLoader").modal('hide');  
                    if (data) {  
                        if ('@ViewBag.Status' == 'Add')  
                            alert("Student successfully added");  
                        else if ('@ViewBag.Status' == 'Edit')  
                            alert("Student successfully updated");  
                        window.location.href = "#/Student/Index";  
                    }  
                    else {  
                        alert('Something went wrong');  
                    }  
                },  
                error: function () {  
                    alert('Something went wrong');  
                }  
            });  
        });  
    }  
  
</script>  

Now, run the application.

Image 4

Image 5

Image 6

Edit Student

Now, move on to Edit Module. Add Edit actions in Controller.

public ActionResult Edit(int studentID) // studentID nothing but parameter name which we pass in layout-routing.  
        {  
            var student = StudentData.GetStudentById(studentID);  
            ViewBag.Status = "Edit";  
            return PartialView("Add", student);  
        }  
  
        [HttpPost]  
        public ActionResult Update(Student student)  
        {  
            StudentData.UpdateStudent(student);  
            return Json(true, JsonRequestBehavior.AllowGet);  
        }  

We used the same partial view for add and edit, so there  is no need to create a new View for edit. 

After adding the action methods, just run the application.

Image 7

Image 8

Image 9

Delete Student 

Now, we will implement the Delete operation.

We have already written Delete button's code in Student Index.cshtml.

function GetStudents() {  
        $.get("/Student/_Index/", function (data) {  
            $("#StudentDiv").html(data);  
        });  
    }  
  
    function DeleteStudent(studentID) {  
        if (confirm("Delete student?")) {  
            $.get("/Student/Delete/", { studentID: studentID }, function (data) {  
                GetStudents();  
            });  
        }  
    }  

Run the application.

Image 10

Image 11

I hope you have enjoyed this article. Your valuable feedback, questions, or comments about this article are always welcome.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer EY
India India
I Have over 3.5 Year experience in Microsoft Technologies(ASP.NET MVC 4, 5, ASP.NET Core), Jquery and other stuffs. Currently Working in EY (Ernst & Young) Company.

Comments and Discussions

 
Questionsource code!! Pin
faina11-Jun-18 20:52
professionalfaina11-Jun-18 20:52 
QuestionFew questions on the code example Pin
Mou_kol10-Jun-18 23:14
Mou_kol10-Jun-18 23:14 
QuestionOne request please upload the source code in zip format Pin
Mou_kol10-Jun-18 23:03
Mou_kol10-Jun-18 23:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.