Traffy
Traffy

Reputation: 2861

MVC4 - AutoComplete using Json

I'm working on an intranet web app using ASP.NET MVC4 and Entity Framework. On one of my views, I have a list of persons which might be huge in the future. So, to make things easier, I wanted to implement an autocomplete field component using jQuery UI and Json.

The thing is that when I'm using my database to provide a source to my jQuery code, it is not working. However, when I create a variable by hard coding data, it works.

My Action :

public ActionResult AutoComplete(string term)
{
    BuSIMaterial.Models.BuSIMaterialEntities db = new Models.BuSIMaterialEntities();

    //var result = new [] {"A","B","C","D","E","F"}; with this, it works

    var result = (from obj in db.Persons where obj.FirstName.ToLower().Contains(term.ToLower()) select obj).ToArray(); // with this, it doesn't work

    return Json(result, JsonRequestBehavior.AllowGet);
}

My View :

@{
    ViewBag.Title = "Auto";
}

<h2>Auto</h2>
<label for="persons">Persons : </label><input type="text" id="persons" name="persons"/>

@section Scripts
{
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/jqueryui")
    @Styles.Render("~/Content/themes/base/css")

    <script type="text/javascript" language="javascript">
        $(document).ready(function () {
            $('#persons').autocomplete({
                source: '@Url.Action("AutoComplete")'
            });
        });
    </script>
}

I tried to modify my return type (JsonResult instead of ActionResult) but nothing changes. Any idea to solve this problem?

Upvotes: 0

Views: 4931

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039588

The reason your code doesn't work is because you are attempting to send a domain model to the view which most probably contains circular references in its object graph and is not JSON serializable. To fix the problem do this:

public ActionResult AutoComplete(string term)
{
    BuSIMaterial.Models.BuSIMaterialEntities db = new Models.BuSIMaterialEntities();

    //var result = new [] {"A","B","C","D","E","F"}; with this, it works

    var result = db
        .Persons
        .Where(p => p.FirstName.ToLower().Contains(term.ToLower()))
        .Select(p => p.FirstName) // <!-- That's the important bit you were missing
        .ToList();

    return Json(result, JsonRequestBehavior.AllowGet);
}

Notice how I am projecting the Person entity to a string (taking only its FirstName). In your example you were directly taking the entire Person object which doesn't make sense for the autocomplete plugin as you need to send an array of strings to the view.

Upvotes: 3

Related Questions