Search, sort, paging, insert, update and delete with ASP.Net MVC and bootstrap modal popup PART-2

Sorting, Filtering and Paging MVC Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application Add Filter, Search and Sort to your Tables MVC Paging Done Perfectly MVC Smart Page C# .NET Search Results Pager Paging, sorting, and searching using EF Code first and MVC

To add insert, update and delete feature we are going to use bootstrap modal popup with a single JavaScript method to open any partial view as a modal popup and one method to post the data from modal, which can work for entire application. First we will add some code to our layout view to dynamically add the partial view in it and JavaScript file, then we will add code only one for add new phone, edit and then finally for delete of phone with the help of jQuery.

First of we will create a JavaScript file which will be used to open the partial view as Modal Popup by using bootstrap. For it create a new folder “Appjs” into script folder on the root, and add a new JavaScript “phone.js” file, before discussing the trick we will used to open any partial view as modal popup, here is the complete JavaScript code:

$(function () {
    $.ajaxSetup({ cache: false });
    $("a[data-modal]").on("click", function (e) {        
        $('#myModalContent').load(this.href, function () {
            $('#myModal').modal({
                keyboard: true
            }, 'show');
            bindForm(this);
        });
        return false;
    });
});

function bindForm(dialog) {
    $('form', dialog).submit(function () {
        $('#progress').show();
        $.ajax({
            url: this.action,
            type: this.method,
            data: $(this).serialize(),
            success: function (result) {
                if (result.success) {
                    $('#myModal').modal('hide');
                    $('#progress').hide();
                    location.reload();
                } else {
                    $('#progress').hide();
                    $('#myModalContent').html(result);
                    bindForm();
                }
            }
        });
        return false;
    });
}

If you can notice the first method, it uses a[data-modal], it means we will use data-modal="" with anchor tag to open the modal popup. This method will add the partial view HTML into div with Id myModalContent which we will use latter on the phone view. Second method is simple which will be use to post the data from the modal.

Html code where we will add our partial view by above created JavaScript method, so add following lines to our phone view at the bottom

<!-- modal placeholder-->
<div id='myModal' class='modal fade in'>
    <div class="modal-dialog">
        <div class="modal-content">
            <div id='myModalContent'></div>
        </div>
    </div>
</div>

@section scripts{
    @Scripts.Render("~/scripts/appjs/phones.js")
}

First we will create the Action method for detail in our phone controller, here is the complete action method

// GET: /Phone/Details/5
public ActionResult Details(int id = 0)
{
    Phone phone =  db.Phones.Find(id);
    if (phone == null)
    {
        return HttpNotFound();
    }
    return PartialView("Details", phone);
}

Note, I am return the Details view as a partial view with correct phone detail from database on the basis of phone Id, right click in detail action method and add a view details and adjust the html as given here

@model MvcBootstrapCrud.Models.Phone

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 class="modal-title">Phone Detail</h3>
</div>

<div class="modal-body">
    <div class="form-horizontal">
        <div class="form-group">
            @Html.LabelFor(m => Model.Model, new { @class = "control-label col-sm-3" })
            <div class="col-sm-9">
                @Html.TextBoxFor(m => m.Model, new { @class = "form-control required", @disabled = "disabled"})
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(m => Model.Company, new { @class = "control-label col-sm-3" })
            <div class="col-sm-9">
                @Html.TextBoxFor(m => m.Company, new { @class = "form-control required", @disabled = "disabled"})
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(m => Model.Price, new { @class = "control-label col-sm-3" })
            <div class="col-sm-9">
                @Html.TextBoxFor(m => m.Price, new { @class = "form-control required" , @disabled = "disabled"})
            </div>
        </div>
    </div>
</div>

<div class="modal-footer">
    <button class="btn btn-warning" data-dismiss="modal">Close</button>
</div>

We already added the anchor tag for view, edit and delete in our WebGrid in Part-1 with attribute data-model ="" so clicking on the different icon will open the partial view as a modal popup. Run the application and click on any detail icon we will get the output like this alt text Now create two new action method Create in the same phone controller, one for get and other for post like this

// GET: /Phone/Create
[HttpGet]
public ActionResult Create()
{
    var phone = new Phone();
    return PartialView("Create", phone);
}


// POST: /Phone/Create
[HttpPost]
public JsonResult Create(Phone phone)
{
    if (ModelState.IsValid)
    {
        db.Phones.Add(phone);
        db.SaveChanges();
        return Json(new { success = true });
    }
    return Json(phone, JsonRequestBehavior.AllowGet);
}

Nothing special in these two methods so add the view for create

@model MvcBootstrapCrud.Models.Phone

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 class="modal-title">Add New Phone</h3>
</div>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="modal-body">

        <div class="form-horizontal">
            <div class="form-group">
                @Html.LabelFor(m => Model.Model, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Model, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Model)
                    </div>
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Company, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Company, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Company)
                    </div>
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Price, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Price, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Price)
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="modal-footer">
        <span id="progress" class="text-center" style="display: none;">
            <img src="/images/wait.gif" alt="wiat" />
            Wait..
        </span>

        <input class="btn btn-primary" type="submit" value="Save" />
        <button class="btn btn-warning" data-dismiss="modal">Close</button>
    </div>
}
<script>
    $("form").removeData("validator");
    $("form").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse("form");
</script>

Run an try to add a new phone, it will looks a like this

alt text

Similarly we can add method and view for Edit and Delete, so let’s add them, code for edit action method and view

// GET: /Phone/Edit/5
[HttpGet]
public ActionResult Edit(int id = 0)
{
    var phone = db.Phones.Find(id);
    if (phone == null)
    {
        return HttpNotFound();
    }

    return PartialView("Edit", phone);
}


// POST: /Phone/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Phone phone)
{
    if (ModelState.IsValid)
    {
        db.Entry(phone).State = EntityState.Modified;
        db.SaveChanges();
        return Json(new { success = true });
    }
    return PartialView("Edit", phone);
}
// Complete Edit view HTML 
@model MvcBootstrapCrud.Models.Phone

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 class="modal-title">Edit Phone</h3>
</div>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(m=>m.PhoneId)

    <div class="modal-body">

        <div class="form-horizontal">
            <div class="form-group">
                @Html.LabelFor(m => Model.Model, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Model, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Model)
                    </div>
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Company, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Company, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Company)
                    </div>
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Price, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Price, new { @class = "form-control required" })
                    <div>
                        @Html.ValidationMessageFor(m => m.Price)
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="modal-footer">
        <span id="progress" class="text-center" style="display: none;">
            <img src="/images/wait.gif" alt="wiat" />
            Wait..
        </span>

        <input class="btn btn-primary" type="submit" value="Save" />
        <button class="btn btn-warning" data-dismiss="modal">Close</button>
    </div>
}
<script>
    $("form").removeData("validator");
    $("form").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse("form");
</script>

Output of Edit View

alt text

Action method and View HTML for Delete, I used one for Get, and other for Post, if you want to use the confirmation box of JavaScript then you need only one to Post, but before deleting I am showing complete detail to decide, see the code

// GET: /Phone/Delete/5
public ActionResult Delete(int id = 0)
{
    Phone phone = db.Phones.Find(id);
    if (phone == null)
    {
        return HttpNotFound();
    }
    return PartialView("Delete", phone);
}


//
// POST: /Phone/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
    var phone = db.Phones.Find(id);
    db.Phones.Remove(phone);
    db.SaveChanges();
    return Json(new { success = true });
}
 ////////////   Delete view HTML  ////////////
@model MvcBootstrapCrud.Models.Phone

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 class="modal-title">Delete Phone</h3>
</div>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="modal-body">

        <div class="form-horizontal">
            <div class="form-group">
                @Html.LabelFor(m => Model.Model, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Model, new { @class = "form-control required", @disabled = "disabled" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Company, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Company, new { @class = "form-control required", @disabled = "disabled" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(m => Model.Price, new { @class = "control-label col-sm-3" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Price, new { @class = "form-control required", @disabled = "disabled" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-9 col-sm-offset-3">
                    <h3>
                        <span class="label label-danger">Are you sure to delete this phone?
                        </span>
                    </h3>
                </div>
            </div>
        </div>
    </div>


    <div class="modal-footer">
        <button class="btn btn-primary" data-dismiss="modal">No</button>
        <input class="btn btn-danger" type="submit" value="Yes" />
    </div>
}

Output of delete view: alt text

Some basic CSS which I used to color the textbox and WebGrid paging

.input-validation-error, .required
{
    border-left:5px solid #ee0000 !important;
}
.valid
{
    border-left:5px solid #00aa00 !important;
}
.field-validation-error
{
    color:#990000;
}
.footer {
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 60px;
    background-color: #f5f5f5;
}

tfoot
{
    text-align: right;
}
tfoot > tr > td a:link
{
    color: #fff;
    background-color: #333;
    padding: 5px 10px;
    border-radius: 7px;
}

Conclusion

  • [HttpPost, ActionName("Delete")], we use it to confirm the detetion, it is a way to define what action name you want to call this method
  • We used some JavaScript code at the bottom of Create and Edit view, it is for adding the client side validation, try to change value for price with some invalid value, immediately it will show you the error.
  • As I promised to use the single method to open the modal popup for all the links and only on method for post the data, we achieved, it can be used for entire application, if you want.

I’ll be more than happy to accept the comment and suggestion, If anyone can suggest us any better idea surely we can discuss and share with our users.

Download source code

See Search, sort, paging, .... PART-1

Ali Adravi Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
  • mvc
  • bootstrap
  • modal-popup
  • asp.net
By Ali Adravi On 28 Dec, 14  Viewed: 49,428

Other blogs you may like

mvc search page example with code

MVC Searh page with pagination: It’s very easy to create a search page in asp.net but when I try to create the same in MVC I faced many problems, how to create model, how to keep searched values in search controls, pagination, I found myself nowhere, so start searching for some good examples but... By Ali Adravi   On 25 Aug 2013  Viewed: 40,117

MVC insert update delete and select records

CRUD (Create, Retrieve, Update and Delete) in MVC. When we start to learn new language, first we try to run an application with “Hello World” and then CRUD functionality. So in this article we will see how to select records from database (with WebGrid, pagination and sort functionality), update a... By Ali Adravi   On 17 Aug 2013  Viewed: 105,948

How to create a single thanks page for entire controller in MVC

Sometimes we need a thanks page say we have user registration, change password, activate account functionality in our application then we need a thanks page after registering with our site, to say thanks for registering with us or showing confirmation that your password is successfully changed or... By Hamden   On 30 Jun 2013  Viewed: 3,738

MVC jquery autocomplete with value and text field

In MVC, autocomplete with jquery is the best way to pull data from database and render according to our requirements, so in this article we will use jquery to show the auto complete text box without any ajax controls. We need a method to get the data from database, a controller method to handle the... By Ali Adravi   On 29 Jun 2013  Viewed: 6,997

Upload files with model data in MVC

Upload multiple files with model data in MVC is really very easy, when I started to test by uploading some files, I though it would be more complicated but it is really not. In my previous post [ASP.Net MVC file upload][1], I promised to post soon about how to upload multiple files. When I was... By Ali Adravi   On 04 Jun 2013  Viewed: 25,493