Ajax.BeginForm duplicate view

1.3k views Asked by At

Context: MVC3,JQuery

hello all!
im trying to filter a webgrid by typing into a textbox, problem is, when using Ajax.BeginForm the whole layout is duplicated where the webgrid should be.

this is the same problem as here jquery.unobtrusive-ajax.min causing strange behavior on the view

Controller

        [HttpPost]
        [ChildActionOnly]
        public ViewResult Files(string filePath)
        {
            IEnumerable<File> results = repository.FindBy(f => f.Path.StartsWith(filePath)).Take(5);
            return View("_grid", results);
        }


partial view

@model IEnumerable<DAL.File>
@{
    Layout = null;
}
@{var grid = new WebGrid(Model, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "myGrid");
  grid.Pager(WebGridPagerModes.NextPrevious);

        @grid.GetHtml(tableStyle: "webGrid",
                headerStyle: "header",
                alternatingRowStyle: "alt",
                columns: grid.Columns(
                             grid.Column("Path", "File"),
                                      grid.Column("Size", "Size (bytes)", canSort: true),
                                               grid.Column("User", "Owner")
        ))}


main view

@model IEnumerable<DAL.File>
@{
    Layout = null;
}
@using (Ajax.BeginForm(new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }))
{
    @Html.TextBox("filePath", null, new { onKeyUp = "$('form').submit()" })    
}
div id="myGrid">
    @Html.Partial("_grid", Model)
/div 

Thank you for the help guys, i really need it :)

1

There are 1 answers

0
Darin Dimitrov On

There seem to be a couple of issues with your code that I can see on first sight:

  1. You have disabled the layout in your main view => I don't see where you have referenced the jQuery.js and the jquery.unobtrusive-ajax.js scripts which are required
  2. Your Files controller action is decorated with the [ChildActionOnly] attribute meaning that it cannot be accessed through an Ajax call

I have tried to clean your code a little and provide an example:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var files = IEnumerable<File> results = repository.FindAll();
        return View(files);
    }

    [HttpPost]
    public ActionResult Index(string filePath)
    {
        var files = repository.FindBy(f => f.Path.StartsWith(filePath)).Take(5);
        return View("_grid", files);
    }
}

and then you could have the corresponding Index.cshtml view:

@model IEnumerable<DAL.File>

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>

@using (Ajax.BeginForm(new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid" }))
{
    @Html.TextBox("filePath", null, new { onkeyup = "$('form').submit()" })    
}

<div id="myGrid">
    @Html.Partial("_grid", Model)
</div>

and the _grid.cshtml partial:

@model IEnumerable<DAL.File>
@{
    Layout = null;
}
@{
    var grid = new WebGrid(Model, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "myGrid");
    grid.Pager(WebGridPagerModes.NextPrevious);
    @grid.GetHtml(
        tableStyle: "webGrid",
        headerStyle: "header",
        alternatingRowStyle: "alt",
        columns: grid.Columns(
            grid.Column("Path", "File"),
            grid.Column("Size", "Size (bytes)", canSort: true),
            grid.Column("User", "Owner")
        )
    )
}

Also note that hamerring your server with AJAX requests everytime the user types some key in the textbox is a very bad idea.