Click here to Skip to main content
15,880,392 members
Articles / Web Development / HTML

ASP.NET MVC 5: Building Your First Web Application - Part 3

Rate me:
Please Sign up or sign in to vote.
4.96/5 (13 votes)
11 Aug 2016CPOL10 min read 56.7K   1.1K   24   29
This article talks about how to perform Fetch, Edit, Update and Delete (FEUD) operations in our ASP.NET MVC 5 application.

Introduction

This is Part 3 of the series on Building Web Applications in ASP.NET MVC 5. In Part 1, we've learned about creating a simple database from scratch using Microsoft SQL Server, a brief overview about ASP.NET MVC in general, creating a simple data access using the Entity Framework Database First approach and a simple implementation of a Signup page in MVC . Part 2 of the series talks about the step-by-step process on creating a basic login page and creating a simple role-based page authorization within our MVC 5 application. If you haven't gone through my previous articles then you can refer to the following links:

In this article, we are going to see how to do Fetch, Edit, Update and Delete (FEUD) operations in our MVC 5 application. The idea is to create a simple maintenance page where admin users can modify user profiles. There are many possible ways to implement FEUD operations in MVC depending on your business needs. For this specific demo, we are going to use jQuery and jQuery AJAX to do asynchronous operations in our page.

Let's Get Started!

If you're ready, then lets do this!

Fetching and Displaying Data

For this example, we're going to create a partial view for displaying the list of users from the database. Partial Views allow you to define a view that will be rendered inside a main view. If you have used WebForms before, then you can think of partial views as user controls (.ascx) which enables you to customize and reuse components.

Adding the View Models

The first thing we need is to create view models for our view. Add the following code within the “UserModel” class:

C#
    public class UserProfileView  
    {  
        [Key]  
        public int SYSUserID { get; set; }  
        public int LOOKUPRoleID { get; set; }  
        public string RoleName { get; set; }  
        public bool? IsRoleActive { get; set; }  
        [Required(ErrorMessage = "*")]  
        [Display(Name = "Login ID")]  
        public string LoginName { get; set; }  
        [Required(ErrorMessage = "*")]  
        [Display(Name = "Password")]  
        public string Password { get; set; }  
        [Required(ErrorMessage = "*")]  
        [Display(Name = "First Name")]  
        public string FirstName { get; set; }  
        [Required(ErrorMessage = "*")]  
        [Display(Name = "Last Name")]  
        public string LastName { get; set; }  
        public string Gender { get; set; }  
    }  
  
    public class LOOKUPAvailableRole  
    {  
        [Key]  
        public int LOOKUPRoleID { get; set; }  
        public string RoleName { get; set; }  
        public string RoleDescription { get; set; }  
    }  
  
    public class Gender  
    {  
        public string Text { get; set; }  
        public string Value { get; set; }  
    } 
 
    public class UserRoles  
    {  
        public int? SelectedRoleID { get; set; }  
        public IEnumerable<LOOKUPAvailableRole> UserRoleList { get; set; }  
    }  
  
    public class UserGender  
    {  
        public string SelectedGender { get; set; }  
        public IEnumerable<Gender> Gender { get; set; }  
    } 
 
    public class UserDataView  
    {  
        public IEnumerable<UserProfileView> UserProfile { get; set; }  
        public UserRoles UserRoles { get; set; }  
        public UserGender UserGender { get; set; }  
    }

The code above are just classes that hold some properties that we need. If you still remember, view models are classes that house some properties that we only need for the view or page.

Adding the ManageUserPartial view

Open the “UserManager” class and declare the namespace below:

C#
using System.Collections.Generic; 

The namespace above contains interfaces and classes that define generic collections that allow us to create strongly-typed collections. Now, add the following code to the “UserManager” class:

C#
public List < LOOKUPAvailableRole > GetAllRoles() {  
    using(DemoDBEntities db = new DemoDBEntities()) {  
        var roles = db.LOOKUPRoles.Select(o = > new LOOKUPAvailableRole {  
            LOOKUPRoleID = o.LOOKUPRoleID,  
            RoleName = o.RoleName,  
            RoleDescription = o.RoleDescription  
        }).ToList();  
  
        return roles;  
    }  
}  
  
public int GetUserID(string loginName) {  
    using(DemoDBEntities db = new DemoDBEntities()) {  
        var user = db.SYSUsers.Where(o = > o.LoginName.Equals(loginName));  
        if (user.Any()) return user.FirstOrDefault().SYSUserID;  
    }  
    return 0;  
}
  
public List<UserProfileView> GetAllUserProfiles() {  
    List <UserProfileView> profiles = new List <UserProfileView>(); 
 
    using(DemoDBEntities db = new DemoDBEntities()) {  
        UserProfileView UPV;  
        var users = db.SYSUsers.ToList();  
  
        foreach(SYSUser u in db.SYSUsers) {  
            UPV = new UserProfileView();  
            UPV.SYSUserID = u.SYSUserID;  
            UPV.LoginName = u.LoginName;  
            UPV.Password = u.PasswordEncryptedText;  
  
            var SUP = db.SYSUserProfiles.Find(u.SYSUserID);  
            if (SUP != null) {  
                UPV.FirstName = SUP.FirstName;  
                UPV.LastName = SUP.LastName;  
                UPV.Gender = SUP.Gender;  
            }  
  
            var SUR = db.SYSUserRoles.Where(o = > o.SYSUserID.Equals(u.SYSUserID));  
            if (SUR.Any()) {  
                var userRole = SUR.FirstOrDefault();  
                UPV.LOOKUPRoleID = userRole.LOOKUPRoleID;  
                UPV.RoleName = userRole.LOOKUPRole.RoleName;  
                UPV.IsRoleActive = userRole.IsActive;  
            }  
  
            profiles.Add(UPV);  
        }  
    }  
  
    return profiles;  
}  
  
public UserDataView GetUserDataView(string loginName) {  
    UserDataView UDV = new UserDataView();  
    List<UserProfileView> profiles = GetAllUserProfiles();  
    List<LOOKUPAvailableRole> roles = GetAllRoles();  
  
    int? userAssignedRoleID = 0, userID = 0;  
    string userGender = string.Empty;  
  
    userID = GetUserID(loginName);  
    using(DemoDBEntities db = new DemoDBEntities()) {  
        userAssignedRoleID = db.SYSUserRoles.Where(o = > o.SYSUserID == userID)?.FirstOrDefault().LOOKUPRoleID;  
        userGender = db.SYSUserProfiles.Where(o = > o.SYSUserID == userID)?.FirstOrDefault().Gender;  
    }  
  
    List<Gender> genders = new List<Gender>();  
    genders.Add(new Gender {  
        Text = "Male", Value = "M"  
    });  
    genders.Add(new Gender {  
        Text = "Female", Value = "F"  
    });  
  
    UDV.UserProfile = profiles;  
    UDV.UserRoles = new UserRoles {  
        SelectedRoleID = userAssignedRoleID, UserRoleList = roles  
    };
  
    UDV.UserGender = new UserGender {  
        SelectedGender = userGender, Gender = genders  
    };
  
    return UDV;  
} 

The methods shown from the code above is pretty much self-explanatory as their method names suggest. The main method there is the GetUserDataView(), and what it does is it gets all user profiles and roles from our database. The UserProfile property holds the users data. Finally, the UserRoles and UserGender properties will be used during the editing and updating of the user data. We will use these values to populate the dropdown lists for roles and gender. 

Adding the ManageUserPartial Action Method

Open the “HomeController” class and add the following namespaces:

C#
using System.Web.Security;  
using MVC5RealWorld.Models.ViewModel;  
using MVC5RealWorld.Models.EntityManager;  

And then add the following action method below:

C#
[AuthorizeRoles("Admin")]  
public ActionResult ManageUserPartial() {  
   if (User.Identity.IsAuthenticated) {  
      string loginName = User.Identity.Name;  
      UserManager UM = new UserManager();  
      UserDataView UDV = UM.GetUserDataView(loginName);  
      return PartialView(UDV);  
   } 
 
   return View();  
}

The code above is decorated with the custom AuthorizeRoles attribute that we have created in Part 2, so that only admin users can invoke that method. What it does is it calls the GetUserDataView() method by passing in the loginName as the parameter, and then return the result in the Partial View.

Adding the ManageUserPartial Partial View

Now let's create the partial view. Right-click on the ManageUserPartial() method and select “Add New” view. This will bring up the following dialog:

Image 1

Figure 1: Add View Dialog

Since we will be creating a custom view for managing users, then just select an “Empty” template and be sure to tick the “Create as a partial view” option. Click Add and then copy the following HTML markup below:

Razor
@model MVC5RealWorld.Models.ViewModel.UserDataView  
  
<div>  
    <h1>List of Users</h1>  
    <table class="table table-striped table-condensed table-hover">  
        <thead>  
            <tr>  
                <th>ID</th>  
                <th>Login ID</th>  
                <th>Password</th>  
                <th>First Name</th>  
                <th>Last Name</th>  
                <th>Gender</th>  
                <th colspan="2">Role</th>  
                <th></th>  
                <th></th>  
            </tr>  
        </thead>  
        <tbody>  
            @foreach (var i in Model.UserProfile) {  
                <tr>  
                    <td> @Html.DisplayFor(m => i.SYSUserID)</td>  
                    <td> @Html.DisplayFor(m => i.LoginName)</td>  
                    <td> @Html.DisplayFor(m => i.Password)</td>  
                    <td> @Html.DisplayFor(m => i.FirstName)</td>  
                    <td> @Html.DisplayFor(m => i.LastName)</td>  
                    <td> @Html.DisplayFor(m => i.Gender)</td>  
                    <td> @Html.DisplayFor(m => i.RoleName)</td>  
                    <td> @Html.HiddenFor(m => i.LOOKUPRoleID)</td>  
                    <td><a href="javascript:void(0)" class="lnkEdit">Edit</a></td>  
                    <td><a href="javascript:void(0)" class="lnkDelete">Delete</a></td>  
                </tr>  
            }  
        </tbody>  
    </table>  
</div>

The markup above uses Razor syntax to iterate the UserProfile view model and assign each field in a <td> element. Now open the “AdminOnly.cshtml” view and add the following markup:

Razor
<div id="divUserListContainer">  
    @Html.Action("ManageUserPartial", "Home");  
</div>

The markup above simply loads the ManageUserPartial partial view within AdminOnly view.

Testing the App

Now try to login to your web page then navigate to: http://localhost:15599/Home/AdminOnly. The output should result to something like this:

Image 2

Figure 2: Fetch Output

Pretty easy, right? :) Now let's move to the next step.

Editing and Updating the Data

Since we will use jQueryUI for providing a dialog box for the user to edit the data, then we need to add a reference to it first. To do that, just right-click on your project and then select Manage Nuget Packages. In the search box type in “jquery” and select “jQuery.UI.Combined” as shown in the image below:

Image 3

Figure 3: Manage Nuget Packages

Once installed, the jQueryUI library should be added to your project under the “Script” folder:

Image 4

Figure 4: jQueryUI Reference

Now, go to Views > Shared >_Layout.cshtml and add the jQueryUI reference in the following order:

ASP.NET
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui-1.11.4.min.js"></script>

The jQueryUI should be added after the jQuery since jQueryUI uses the core jQuery library under the hood.

Now add the jQueryUI CSS reference as in the following:

ASP.NET
<link href="~/Content/themes/base/all.css" rel="stylesheet" /> 

Our _Layout.cshtml markup should now look something like below with the added references to jQuery and jQueryUI:

ASP.NET
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery-ui-1.11.4.min.js"></script>
    <link href="~/Content/themes/base/all.css" rel="stylesheet" />
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                </ul>
            </div>
        </div>
    </div>

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    
    <script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>

Adding the UpdateUserAccount() Method

Keep in mind that this demo is intended to make an app as simple as possible. In complex real scenarios, I would strongly suggest you use a Repository pattern and Unit-of-Work for your data access layer.

Lets keep rolling. Now, add the following code within the “UserManager” class:

C#
public void UpdateUserAccount(UserProfileView user) {  
  
    using(DemoDBEntities db = new DemoDBEntities()) {  
        using(var dbContextTransaction = db.Database.BeginTransaction()) {  
            try {  
  
                SYSUser SU = db.SYSUsers.Find(user.SYSUserID);  
                SU.LoginName = user.LoginName;  
                SU.PasswordEncryptedText = user.Password;  
                SU.RowCreatedSYSUserID = user.SYSUserID;  
                SU.RowModifiedSYSUserID = user.SYSUserID;  
                SU.RowCreatedDateTime = DateTime.Now;  
                SU.RowMOdifiedDateTime = DateTime.Now;  
  
                db.SaveChanges();  
  
                var userProfile = db.SYSUserProfiles.Where(o = > o.SYSUserID == user.SYSUserID);  
                if (userProfile.Any()) {  
                    SYSUserProfile SUP = userProfile.FirstOrDefault();  
                    SUP.SYSUserID = SU.SYSUserID;  
                    SUP.FirstName = user.FirstName;  
                    SUP.LastName = user.LastName;  
                    SUP.Gender = user.Gender;  
                    SUP.RowCreatedSYSUserID = user.SYSUserID;  
                    SUP.RowModifiedSYSUserID = user.SYSUserID;  
                    SUP.RowCreatedDateTime = DateTime.Now;  
                    SUP.RowModifiedDateTime = DateTime.Now;  
  
                    db.SaveChanges();  
                }  
  
                if (user.LOOKUPRoleID > 0) {  
                    var userRole = db.SYSUserRoles.Where(o = > o.SYSUserID == user.SYSUserID);  
                    SYSUserRole SUR = null;  
                    if (userRole.Any()) {  
                        SUR = userRole.FirstOrDefault();  
                        SUR.LOOKUPRoleID = user.LOOKUPRoleID;  
                        SUR.SYSUserID = user.SYSUserID;  
                        SUR.IsActive = true;  
                        SUR.RowCreatedSYSUserID = user.SYSUserID;  
                        SUR.RowModifiedSYSUserID = user.SYSUserID;  
                        SUR.RowCreatedDateTime = DateTime.Now;  
                        SUR.RowModifiedDateTime = DateTime.Now;  
                    } else {  
                        SUR = new SYSUserRole();  
                        SUR.LOOKUPRoleID = user.LOOKUPRoleID;  
                        SUR.SYSUserID = user.SYSUserID;  
                        SUR.IsActive = true;  
                        SUR.RowCreatedSYSUserID = user.SYSUserID;  
                        SUR.RowModifiedSYSUserID = user.SYSUserID;  
                        SUR.RowCreatedDateTime = DateTime.Now;  
                        SUR.RowModifiedDateTime = DateTime.Now;  
                        db.SYSUserRoles.Add(SUR);  
                    }  
  
                    db.SaveChanges();  
                }  
                dbContextTransaction.Commit();  
            } catch {  
                dbContextTransaction.Rollback();  
            }  
        }  
    }  
}

The method above takes a UserProfileView object as the parameter. This parameter is coming from a strongly-typed View. What it does is it first issues a query to the database using the LINQ syntax to get the specific user data by passing the SYSUserID. It then updates the SYSUser object with the corresponding data from the UserProfileView object. The second query gets the associated SYSUserProfiles data and then updates the corresponding values. After that, it then looks for the associated LOOKUPRoleID for a certain user. If the user doesn’t have role assigned to it, then it adds a new record to the database, otherwise just update the table. 

If you also notice, we used a simple transaction within that method. This is because the tables SYSUser, SYSUserProfile and SYSUserRole have dependencies to each other, and we need to make sure that we only commit changes to the database if the operation for each table is successful. The Database.BeginTransaction() is only available in EF 6 onwards.

Adding the UpdateUserData() Action Method

Add the following code within the “HomeController” class:

C#
[AuthorizeRoles("Admin")]  
public ActionResult UpdateUserData(int userID, string loginName, string password, 
string firstName, string lastName, string gender, int roleID = 0) {  
    UserProfileView UPV = new UserProfileView();  
    UPV.SYSUserID = userID;  
    UPV.LoginName = loginName;  
    UPV.Password = password;  
    UPV.FirstName = firstName;  
    UPV.LastName = lastName;  
    UPV.Gender = gender;  
  
    if (roleID > 0)  
      UPV.LOOKUPRoleID = roleID;  
  
      UserManager UM = new UserManager();  
      UM.UpdateUserAccount(UPV);  
  
      return Json(new { success = true });  
}

The method above is responsible for collecting data that is sent from the View for update. It then calls the method UpdateUserAccount() and pass the UserProfileView model view as the parameter. The UpdateUserData() method will be called through an AJAX request. Note that you can also use Web API to send and recieve data via AJAX. Though we will not be covering that here for the simplicity of this demo.

Modifying the UserManagePartial View

Add the following HTML markup within “UserManagePartial.cshtml”:

Razor
<div id="divEdit" style="display:none">  
    <input type="hidden" id="hidID" />  
    <table>  
        <tr>  
            <td>Login Name</td>  
            <td>  
                <input type="text" id="txtLoginName" class="form-control" />  
            </td>  
        </tr>  
        <tr>  
            <td>Password</td>  
            <td>  
                <input type="text" id="txtPassword" class="form-control" />  
            </td>  
        </tr>  
        <tr>  
            <td>First Name</td>  
            <td>  
                <input type="text" id="txtFirstName" class="form-control" />  
            </td>  
        </tr>  
        <tr>  
            <td>Last Name</td>  
            <td>  
                <input type="text" id="txtLastName" class="form-control" />  
            </td>  
        </tr>  
        <tr>  
            <td>Gender</td>  
            <td>@Html.DropDownListFor(o => o.UserGender.SelectedGender,  
                       new SelectList(Model.UserGender.Gender, "Value", "Text"),  
                       "",  
                       new { id = "ddlGender", @class="form-control" })  
            </td>  
        </tr>  
        <tr>  
            <td>Role</td>  
            <td>@Html.DropDownListFor(o => o.UserRoles.SelectedRoleID,   
                       new SelectList(Model.UserRoles.UserRoleList, "LOOKUPRoleID", "RoleName"),   
                       "",   
                       new { id = "ddlRoles", @class="form-control" })  
            </td>  
        </tr>  
    </table>  
</div>

The markup above will serve as our popup diaog when a user edits a particular user data. Notice that we are populating the DropDowns for Gender and Roles with data from our Model.

Integrating jQuery and jQuery AJAX

Before we go to the implementation it’s important to know what these technologies are:

  • jQuery is a light weight and feature-rich JavaScript library that enable DOM manipulation, even handling, animation and Ajax much simpler with powerful API that works across all major browsers.
  • jQueryUI provides a set of UI interactions, effects, widgets and themes built on top of the jQuery library.
  • jQuery AJAX enables you to use high level functions and methods to communicate with your data from the server, and loads your data to the client/browser.

Now switch back to the “UserManagePartial” view and add the following script block at the very bottom:

JavaScript
<script type="text/javascript">    
    $(function () {    
    
        var initDialog = function (type) {    
            var title = type;    
            $("#divEdit").dialog({    
                autoOpen: false,    
                modal: true,    
                title: type + ' User',    
                width: 360,    
                buttons: {    
                    Save: function () {    
                        var id = $("#hidID").val();    
                        var role = $("#ddlRoles").val();    
                        var loginName = $("#txtLoginName").val();    
                        var loginPass = $("#txtPassword").val();    
                        var fName = $("#txtFirstName").val();    
                        var lName = $("#txtLastName").val();    
                        var gender = $("#ddlGender").val();    
    
                        UpdateUser(id, loginName, loginPass, fName, lName, gender, role);    
                        $(this).dialog("destroy");    
                    },    
                    Cancel: function () { $(this).dialog("destroy"); }    
                }    
            });    
        }    
    
        function UpdateUser(id, logName, logPass, fName, lName, gender, role) {    
            $.ajax({    
                type: "POST",    
                url: "@(Url.Action("UpdateUserData","Home"))",    
                data: { userID: id, loginName: logName, password: logPass, firstName: fName, lastName: lName, gender: gender, roleID: role },    
                success: function (data) {    
                    $("#divUserListContainer").load("@(Url.Action("ManageUserPartial","Home", new { status ="update" }))");    
                },    
                error: function (error) {    
                    //to do:    
                }    
            });    
        }    
    
        $("a.lnkEdit").on("click", function () {    
            initDialog("Edit");    
            $(".alert-success").empty();    
            var row = $(this).closest('tr');    
    
            $("#hidID").val(row.find("td:eq(0)").html().trim());    
            $("#txtLoginName").val(row.find("td:eq(1)").html().trim())    
            $("#txtPassword").val(row.find("td:eq(2)").html().trim())    
            $("#txtFirstName").val(row.find("td:eq(3)").html().trim())    
            $("#txtLastName").val(row.find("td:eq(4)").html().trim())    
            $("#ddlGender").val(row.find("td:eq(5)").html().trim())    
            $("#ddlRoles").val(row.find("td:eq(7) > input").val().trim());    
    
            $("#divEdit").dialog("open");    
            return false;    
        });    
    });    
    
</script>

The initDialog initializes the jQueryUI dialog by customizing the dialog. We customized it by adding our own Save and Cancel buttons for us to write custom code implemetation for each event. In the Save function we extracted each value from the edit form and passed these values to the UpdateUser() JavaScript function.

The UpdateUser() function issues an AJAX request using jQuery AJAX. The "type" parameter indicates what form method the request requires, in this case we set the type as "POST". The "url" is the path to the controller's method that we have created earlier. Note that the value of url can be a web service, Web API or anything that host your data. The "data" is where we assign values to the method that requires parameter. If your method in the server doesn't require any parameter then you can leave this as empty "{}". The "success" function is usually used when you do a certain process if the request from the server succeeds. In this case we load the Partial View to reflect the changes on the view after we update the data. Keep in mind that we are passing a new parameter to the "ManageUserPartial" action that indicates the status of the request.

The last function is where we open the dialog when the user clicks on the "edit" link from the grid. This is also where we extract the data from the grid using jQuery selectors and populate the dialog fields with the extracted data.

Modifying the UserManagePartial() Action Method

If you remember, we added the new parameter “status” to the UserManagePartial method call in our AJAX request, so we need to update the method signature to accept a parameter. The new method should now look something like this:

C#
[AuthorizeRoles("Admin")]  
public ActionResult ManageUserPartial(string status = "") {  
    if (User.Identity.IsAuthenticated) {  
        string loginName = User.Identity.Name;  
        UserManager UM = new UserManager();  
        UserDataView UDV = UM.GetUserDataView(loginName);  
  
        string message = string.Empty;  
        if (status.Equals("update")) message = "Update Successful";  
        else if (status.Equals("delete")) message = "Delete Successful";  
  
        ViewBag.Message = message;  
  
        return PartialView(UDV);  
    }  
  
    return RedirectToAction("Index", "Home");  
}

Displaying the Status Result

If you have noticed, we are creating a message string based on a certain operation and store the result in ViewBag. This is to let user see if a certain operation succeeds. Now add the following markup below within “ManageUserPartial” view:

HTML
<span class="alert-success">@ViewBag.Message</span>  

Testing the App

Running the app will result to the following outputs below:

After clicking the edit dialog

Image 5

Figure 5: Edit User Dialog

Editing the data

Image 6

Figure 6: Editing User Data

and after successful update

Image 7

Figure 7: Successful Update

If you've made it this far then congratulations!, you're now ready for the next step. Now down to the last part of this series.

Deleting Data

Adding the DeleteUser() Method

Add the following method to the “UserManager” class:

C#
public void DeleteUser(int userID) {  
    using(DemoDBEntities db = new DemoDBEntities()) {  
        using(var dbContextTransaction = db.Database.BeginTransaction()) {  
            try {  
  
                var SUR = db.SYSUserRoles.Where(o = > o.SYSUserID == userID);  
                if (SUR.Any()) {  
                    db.SYSUserRoles.Remove(SUR.FirstOrDefault());  
                    db.SaveChanges();  
                }  
  
                var SUP = db.SYSUserProfiles.Where(o = > o.SYSUserID == userID);  
                if (SUP.Any()) {  
                    db.SYSUserProfiles.Remove(SUP.FirstOrDefault());  
                    db.SaveChanges();  
                }  
  
                var SU = db.SYSUsers.Where(o = > o.SYSUserID == userID);  
                if (SU.Any()) {  
                    db.SYSUsers.Remove(SU.FirstOrDefault());  
                    db.SaveChanges();  
                }  
  
                dbContextTransaction.Commit();  
            } catch {  
                dbContextTransaction.Rollback();  
            }  
        }  
    }  
}

The method above deletes the record for a specific user in the SYSUserRole, SYSUserProfile and SYSUser tables. Notice that we also used a Transaction to ensure that no operation will committed for each tables if something went wrong or fail.

Adding the DeleteUser() Action Method

Add the following code within the “HomeController” class:

C#
[AuthorizeRoles("Admin")]  
public ActionResult DeleteUser(int userID) {  
   UserManager UM = new UserManager();  
   UM.DeleteUser(userID);  
   return Json(new { success = true });  
}

There nothing much to tell about the method above. As the method name suggests, it will delete a particular user in the database based on the SYSUserID.

Integrating jQuery and jQuery AJAX

Add the following script within the <script> tag in the "UserManagePartial" view:

JavaScript
function DeleteUser(id) {  
    $.ajax({  
        type: "POST",  
        url: "@(Url.Action("  
        DeleteUser ","  
        Home "))",  
        data: {  
            userID: id  
        },  
        success: function(data) {  
            $("#divUserListContainer").load("@(Url.Action("  
            ManageUserPartial ","  
            Home ", new { status ="  
            delete " }))");  
        },  
        error: function(error) {}  
    });  
}  
  
$("a.lnkDelete").on("click", function() {  
    var row = $(this).closest('tr');  
    var id = row.find("td:eq(0)").html().trim();  
    var answer = confirm("You are about to delete this user with ID " + id + " . Continue?");  
    if (answer) DeleteUser(id);  
    return false;  
});

There are towo main functions from the code above. The DeleteUser() function takes an ID as the parameter. This method is where we call the DeleteUser() action method we defined in the Controller. It will then load back the list of users if the delete operation is successful. The other function simply binds a JQuery click event to the links within the grid. It is also where we show a confirmation dialog to prompt users if they want to delete a record or not. If a user clicks on "yes", then it will call the JavaScript DeleteUser() function to execute the deletion.

Testing the App

Here are the outputs below:

After clicking the delete link

Image 8

Figure 8: Delete Confirmation Dialog

and after the deletion

Image 9

Figure 9: After Successful Deletion

In the next part of this series, we will see how to implement a simple user profile page wherein users can modify their data. You can check the next part here: ASP.NET MVC 5: Building Your First Web Application - Part 4

Summary

In thi series, we've learned how to implement a basic FEUD operations in our ASP.NET MVC 5 app. We have also learned how to use a simple AJAX call to communicate with our data from the server.

 

License

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


Written By
Architect
United States United States
A code monkey who loves to drink beer, play guitar and listen to music.

My Tech Blog: https://vmsdurano.com/
My Youtube Channel: https://www.youtube.com/channel/UCuabaYm8QH4b1MAclaRp-3Q

I currently work as a Solutions Architect and we build "cool things" to help people improve their health.

With over 14 years of professional experience working as a Sr. Software Engineer specializing mainly on Web and Mobile apps using Microsoft technologies. My exploration into programming began at the age of 15;Turbo PASCAL, C, C++, JAVA, VB6, Action Scripts and a variety of other equally obscure acronyms, mainly as a hobby. After several detours, I am here today on the VB.NET to C# channel. I have worked on Web Apps + Client-side technologies + Mobile Apps + Micro-services + REST APIs + Event Communication + Databases + Cloud + Containers , which go together like coffee crumble ice cream.

I have been awarded Microsoft MVP each year since 2009, awarded C# Corner MVP for 2015, 2016,2017 and 2018, CodeProject MVP, MVA, MVE, Microsoft Influencer, Dzone MVB, Microsoft ASP.NET Site Hall of Famer with All-Star level and a regular contributor at various technical community websites such as CSharpCorner, CodeProject, ASP.NET and TechNet.

Books written:
" Book: Understanding Game Application Development with Xamarin.Forms and ASP.NET
" Book (Technical Reviewer): ASP.NET Core and Angular 2
" EBook: Dockerizing ASP.NET Core and Blazor Applications on Mac
" EBook: ASP.NET MVC 5- A Beginner's Guide
" EBook: ASP.NET GridView Control Pocket Guide

Comments and Discussions

 
QuestionError CS0103 The name 'o' does not exist in the current context Pin
Member 107897589-May-18 23:29
Member 107897589-May-18 23:29 
AnswerRe: Error CS0103 The name 'o' does not exist in the current context Pin
Vincent Maverick Durano17-Sep-18 4:47
professionalVincent Maverick Durano17-Sep-18 4:47 
QuestionJavaScript dropdown Pin
Member 1258366220-Mar-17 2:10
Member 1258366220-Mar-17 2:10 
AnswerRe: JavaScript dropdown Pin
Vincent Maverick Durano20-Mar-17 11:52
professionalVincent Maverick Durano20-Mar-17 11:52 
GeneralRe: JavaScript dropdown Pin
Member 1258366220-Mar-17 22:16
Member 1258366220-Mar-17 22:16 
GeneralRe: JavaScript dropdown Pin
Vincent Maverick Durano20-Mar-17 22:32
professionalVincent Maverick Durano20-Mar-17 22:32 
GeneralRe: JavaScript dropdown Pin
Member 1258366221-Mar-17 6:28
Member 1258366221-Mar-17 6:28 
GeneralRe: JavaScript dropdown Pin
Vincent Maverick Durano21-Mar-17 14:31
professionalVincent Maverick Durano21-Mar-17 14:31 
GeneralRe: JavaScript dropdown Pin
Member 1258366221-Mar-17 22:30
Member 1258366221-Mar-17 22:30 
GeneralRe: JavaScript dropdown Pin
Member 1258366224-Mar-17 3:38
Member 1258366224-Mar-17 3:38 
GeneralRe: JavaScript dropdown Pin
Member 1258366227-Mar-17 21:07
Member 1258366227-Mar-17 21:07 
GeneralRe: JavaScript dropdown Pin
Vincent Maverick Durano28-Mar-17 15:35
professionalVincent Maverick Durano28-Mar-17 15:35 
QuestionUpdation is not working Pin
Member 1258366214-Mar-17 21:01
Member 1258366214-Mar-17 21:01 
AnswerRe: Updation is not working Pin
Vincent Maverick Durano15-Mar-17 18:32
professionalVincent Maverick Durano15-Mar-17 18:32 
QuestionHow the ViewModel works Pin
Member 1258366212-Mar-17 17:54
Member 1258366212-Mar-17 17:54 
AnswerRe: How the ViewModel works Pin
Vincent Maverick Durano12-Mar-17 22:08
professionalVincent Maverick Durano12-Mar-17 22:08 
GeneralRe: How the ViewModel works Pin
Member 1258366213-Mar-17 21:39
Member 1258366213-Mar-17 21:39 
GeneralRe: How the ViewModel works Pin
Vincent Maverick Durano14-Mar-17 14:53
professionalVincent Maverick Durano14-Mar-17 14:53 
QuestionJavascript:void(0) does not work Pin
e$heldon15-Feb-17 12:46
e$heldon15-Feb-17 12:46 
AnswerRe: Javascript:void(0) does not work Pin
Vincent Maverick Durano20-Feb-17 13:26
professionalVincent Maverick Durano20-Feb-17 13:26 
GeneralRe: Javascript:void(0) does not work Pin
Member 1258366212-Mar-17 21:06
Member 1258366212-Mar-17 21:06 
GeneralRe: Javascript:void(0) does not work Pin
Vincent Maverick Durano12-Mar-17 22:11
professionalVincent Maverick Durano12-Mar-17 22:11 
GeneralRe: Javascript:void(0) does not work Pin
Member 1258366213-Mar-17 19:44
Member 1258366213-Mar-17 19:44 
GeneralRe: Javascript:void(0) does not work Pin
Vincent Maverick Durano14-Mar-17 14:55
professionalVincent Maverick Durano14-Mar-17 14:55 
GeneralRe: Javascript:void(0) does not work Pin
Member 1258366214-Mar-17 18:34
Member 1258366214-Mar-17 18:34 

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.