Filtering Data in ASP.NET MVC using jQuery and Partial Views

Recently I completed an ASP.NET MVC workshop where we discussed several advantages of using jQuery in MVC. During the session, one of the attendee wanted to know how to filter data in the ‘Index’ view based upon the matching search string passed from the view. In this article, we will see a simple solution for this problem.

Also read - ASP.NET MVC: Displaying Partial Views using jQuery UI Dialog Boxes and Using jQuery for displaying ASP.NET MVC Partial View to Perform Edit Operation

Building the Sample Application

Here I have used jQuery for the scripting on the client side. The $.ajax method of jQuery is used to make asynchronous calls to the controller action method to fetch the filtered data.

The Backend

For the application, I have used Sql Server 2008 R2 with database as ‘Company’, Visual Studio 2012 RC and MVC 3. The below table I have used for the application.

CREATE TABLE [dbo].[EmployeeInfo](
    [EmpNo] [int] Primary Key IDENTITY(1,1) NOT NULL,
    [EmpName] [varchar](50) NOT NULL,
    [Salary] [decimal](18, 0) NOT NULL,
    [DeptName] [varchar](50) NOT NULL,
    [Designation] [varchar](50) NOT NULL
)


To design the Data Access Layer, I have used the ADO.NET EF as below:

image

Editor’s Note: The Web.Config in Github is configured to connect to (localdb)\v11.0 change the Data Source entry in the connection string to point to your SQL Server database.

The UI

Step 1: Open VS and create an ASP.NET MVC 3 Application, name it as ‘MVC3_MasterDetailsUI’. Add the model using ADO.NET EF for the above EmployeeInfo table.

Step 2: Add a new controller in the Controller folder; name it as ‘NewEmployeeController’. Add the constructor, and the two Index action methods in the controller. The two index methods will be used for Http Get and Http Post operations. The Index with Http Get will be used to display all Employees and Index with Http Post will be used for showing Filtered Employee Records. The implementation will be as below:

using MVC3_MasterDetailsUI.Models;
public class NewEmployeeController : Controller
{
    CompanyEntities objContext;

    public NewEmployeeController()
    {
        objContext = new CompanyEntities();
    }

    // GET: /NewEmployee/
    public ActionResult Index()
    {
        var Employees = objContext.EmployeeInfoes.ToList();
        return View(Employees);
    }

    /// <summary>
    /// MEthod to Display the Filtered Data
    /// </summary>
    /// <param name="emp"></param>
    /// <returns></returns>
    [HttpPost]
    public ActionResult Index(EmployeeInfo emp)
    {
        List<EmployeeInfo> Employees;
        if (emp.EmpName != null)
        {
            Employees = (from Emp in objContext.EmployeeInfoes.ToList()
                         where Emp.EmpName.StartsWith(emp.EmpName)
                         select Emp).ToList();
        }
        else
        {
            Employees = objContext.EmployeeInfoes.ToList();
        }
        return PartialView("EmployeeInfo", Employees);
    }
}


Note that Index method with Http Post, returns a Partial View. We will be creating this in the upcoming steps.

Step 3: Add a new Index View in the project, by right-clicking on the Http Get Index action method, select the scaffold template as ‘List’. This will show the Employee data in the Tabular fashion. This will add a new ‘NewEmployee’ folder as a subfolder of Views folder in the Project and the Index.cshtml in it.

Step 4: Right-Click on the NewEmployee folder and add a new strongly-typed partial view which has Model class as EmployeeInfo and the scaffold template as ‘List’. Name this partial view as ‘EmployeeInfo’. Note that the Index method with HttpPost returns this partial View.

Step 5: Open Index.cshtml and add a new Html Text box and the div tag as below:
Enter the EmpName to Filter:

<input type="text" id="txtfilter" />
<div id="empInfoDetails">  
</div>


Step 6: assign Id to the Html Table tag which shows the List of Employees as ‘tblData’ as below:

<table id="tblData">

Step 7: Write the below Script in the Index.cshtml

<script type="text/javascript" src="../../Scripts/jquery-1.6.2.js"></script>
<script  type="text/javascript">
$(document).ready(function () {
    $("#txtfilter").keyup(function () {
        $("#tblData").hide('fast'); //Hide the Table showing All Data
        $('#empInfoDetails').show('fast'); //Show the <div> showing filtered Data
        var data = $(this).val();
        var url = "/NewEmployee/Index/"; //The Url to the Action  Method of the Controller
        var Emp = {}; //The Object to Send Data Back to the Controller
        Emp.EmpName = $("#txtfilter").val();
        // Check whether the TextBox Contains text
        // if it does then make ajax call
        if ($("#txtfilter").val().length > 0 || $("#txtfilter").val() != "") {
            $.ajax({
                type: 'POST',
                url: url,
                data: Emp,
                dataType: "html",
                success: function (evt) {
                        $('#empInfoDetails').html(evt);
                },
            });
        }
        else
        {
            $('#empInfoDetails').hide('fast'); //Hide the <div>
            $("#tblData").show('fast'); //Hide the Table
        }

    });
});
</script>


The Keyup event of the textbox is used to trigger an Async Postback. When the text is entered in the textbox the table ‘tblData’ is hidden and the ‘empInfoDetails’ div tag is made visible. The event makes an asynchronous POST to the Http Post Index method of the NewEmployee controller and gets the PartialView as a response. This response is shown in the div tag. If the TextBox has no text, then all records will be displayed by making tblData visible again.

Step 8: Add the NewEmployee controller and its Index action in Layout.cshtml of the Shared subfolder under View folder by locating <div> with id as ‘menucontainer’ as below:

<li>@Html.ActionLink("NewEmployee", "Index", "NewEmployee")</li>

Step 9: Run the application and click on the ‘NewEmployee’ Tag, the result will be as below:

clip_image002

Enter a Text in the TextBox labeled as ‘Enter the EmpName to Filter’, you will get the matching result as below:

clip_image004

Conclusion

Partial Views are a handy way of updating parts of a webpage via a Partial Postback. Along with jQuery $.ajax postback, they can be considered as replacement for the UpdatePanel from WebForms world.

Fork the code on Github or Download the zip.




About The Author

Mahesh Sabnis is a Microsoft MVP having over 18 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). He also blogs regularly at DotNetCurry.com. Follow him on twitter @maheshdotnet

6 comments:

Stoo said...

Why use
(from Emp in objContext.EmployeeInfoes.ToList()
where Emp.EmpName.StartsWith(emp.EmpName)
select Emp).ToList();

You load the WHOLE [dbo].[EmployeeInfo] table and then filter it in-memory ???

That's going to kill performance :-(

Why not let EF/SQL do the filtering ?

Anonymous said...

Hi Stoo,

Good catch, the code should read,

Employees = (from Emp in objContext.EmployeeInfoes
where Emp.EmpName.StartsWith(emp.EmpName)
select Emp).ToList();

The ToList() for EmployeeInfoes is extra. We'll fix it shortly.

Code has been updated in the repo.

Christine Mccoy said...

MVC jQuery validation is done on the front end (client side), without submitting data to the controller (Server side). So it can save some bandwidth/processing.you also provide good steps related to that.

Cynthia Kent said...

I'm in the procedure of spinning mikesdotnetting.com using the ASP.NET MVC structure. It's an exciting encounter, in that this is my first contact with MVC. The first hurdle I experienced was how to complete information in a sufficient way to Partially Opinions which only signify aspect of the information that is to be shown in the Perspective.

Unknown said...

You can also try Sprint.Filter
https://github.com/artem-sedykh/Sprint.Filter

Unknown said...

why we use constructor in controller