1

I'm learning MVC and am stumped by this. I'm trying to factor some common code that gets data and displays it in a WebGrid into a partial view that i can use on multiple pages.

My home controller Index method just does a return View(). The Home view looks like this:

@using (Ajax.BeginForm("SearchAction", "Search",
    new AjaxOptions { UpdateTargetId = "data-grid", HttpMethod = "Post" }))
{
    @Html.TextBoxFor(model => model.name)
    <input type="submit" value="Search" />
}

@{
<div id="data-grid">
    @Html.Partial("SearchResults", Model)
</div>
}

I'm trying to use Ajax to avoid losing my search form data when clicking a WebGrid pager link, which are rendered as normal links.

My SearchController looks like this:

public ActionResult SearchAction(string name)
{
    return RedirectToAction("SearchResults", new { name = name });
}

public ActionResult SearchResults(string name)
{
    //does database query and sticks results in the viewbag
    //filter on optional name parameter

    VieweBag.Members = MyQueryResults;
    return PartialView();
}

My SearchResults shared view, data is passed in via ViewBag.Members:

@{
    var grid = new WebGrid(null, rowsPerPage: ViewBag.Pagesize);
    grid.Bind(ViewBag.Members);
    @grid.GetHtml(// etc. etc.)
}

The results I'm getting is that the ViewBag.Pagesize and ViewBag.Members binding fails since there is no data in the viewbag. Obviously, my partial controller is not being called to do the initial query and put stuff in the ViewBag when the home page is first loaded. How do I make that happen?

The other weird thing is that if I just copy the database query code into my home controller (where it originally was) to force the original query, then if I put some text into the search field and do a search, the partial view renders by itself on a new page. Why is that happening, I thought it would only render as part of my home page.

I've cobbled this partial view together from various answers/places and have no doubt gotten something horribly wrong :\

Eric Sassaman
  • 1,401
  • 1
  • 18
  • 23

2 Answers2

2

The partial page won't pass through a controller, but simply render the view directly. If you want to pass view data to the partial view, there is an overloaded function that takes a viewdata dictionary. I'm sorry I can't be more detailed, but I'm on my mobile (waiting for my son to fall asleep in the other room) :)

Update:

If you want to trigger a GET action for your partial view, you can use Html.Action. Here are some useful links:

Further, it would probably make sense for you to move your form tags into your partial view, but those are details for when you clean up the code.

The Jonas Persson
  • 1,726
  • 1
  • 17
  • 36
  • Wait, what does "won't pass through a controller" mean? I'm confused, I have a controller for my partial view, and it's being called, but only when I search... not on page load. How do I force the partial view controller to be called on page load so that the partial view has data? – Eric Sassaman May 04 '13 at 02:42
  • @EricSassaman, I updated my answer. Hope it helps. The partial view, as you have it, won't call the server when the page is first loaded. The controller action that will be triggered depends on how you have your routing setup. However, since you have defined it in the form tag, the search controller will be called on a postback. If you move the form into your partial view, you can target your postback much better (for instance, you might want a different form and postback on the parent page). – The Jonas Persson May 04 '13 at 22:52
  • 1
    Fixed!! My fixes: 1) include jquery.unobtrusive-ajax.js - this fixed the rendering on a separate page. 2) replace @Html.Partial with @Html.Action("SearchResults", "Search"), this loaded the grid on page load (thank you!!) 3) deleted useless SearchAction() in search controller and 4) set HttpMethod = "GET" in Ajax.BeginForm AjaxOptions (doh!). I also had a mismatch between my form input ID and my search controller parameter. Also kudos to the book "Pro ASP.NET MVC 4" for some vital clues during an all-day reading binge, whew. – Eric Sassaman May 05 '13 at 01:41
0

Jonass is right, the ViewBag only propagates between the Controller and the View.

One thing you can do is make the model of the partial view be the same as the type of data you're putting into the ViewBag.

So if for example your MyQueryResults is of type:

IEnumerable<Result>

In your partial view you'd add

@Model IEnumerable<Result>

And then in the main view, you'd pass it through the Render method:

@Html.Partial("SearchResults", ViewBag.Members);

You'll need to tweak this a bit to make sure it's the right type, but this should do the trick.

Good luck!

Russ Clarke
  • 17,511
  • 4
  • 41
  • 45
  • Hm the problem is that my SearchResults controller just never gets called on page load. Only my home page controller does. I tried making your suggested changes and when I put a breakpoint in my partial view controller (SearchController), it never hits it on page load. So my model is null in my partial view. Do I need to duplicate my db query code in both controllers? Totally defeats the purpose of what I'm try to do here... – Eric Sassaman May 04 '13 at 02:35