I have a search form with filters. 1 filter is range which is to be a dropdown with numbers. I have a view using a viewmodal with a ienumerable of search range (my db table) and in the controller i populate this and all works as it should… until the form is displayed and the user tries to filter again in which case my model view ienumerable is now null. Why does it lose the values. Do i need to re-popualte this everytime the users does a new filter… if so can it be done without repeating calls to the database as the values in the dropdown list wont change.
modal view
public class SearchResultsViewModel
{
public int? Page { get; set; }
public penguin.Models.Job Job { get; set; }
public IPagedList<Models.Job> SearchResults { get; set; }
public string SearchButton { get; set; }
[Display(Name = "keywords")]
public string keywords { get; set; }
[Display(Name = "location")]
public string location { get; set; }
public int RangeID { get; set; }
public IEnumerable<Models.SearchRange> Range { get; set; }
}
controller
const int RecordsPerPage = 25;
public ActionResult Jobs(ViewModels.SearchResultsViewModel model)
{
// do something with the search value
if (!string.IsNullOrEmpty(model.SearchButton) || model.Page.HasValue)
{
var entities = new Models.DBDataContext();
var results = entities.Jobs;
var pageIndex = model.Page ?? 1;
model.SearchResults = results.ToPagedList(pageIndex, 25);
//Range = ViewData["Range"] as IEnumerable<Models.SearchRange>;
}
else {
var Data = Helpers.ModelHelpers.GetDataContext();
var ranges = (from r in Data.SearchRanges select r);
model.Range = ranges;
//Range = ranges;
}
//ViewData["Range"] = Range;
//model.Range = Range;
return View(model);
}
View
@using PagedList.Mvc;
@model ViewModels.SearchResultsViewModel
@{
ViewBag.Title = "Jobs";
}
@section search {
@using (Html.BeginForm("Jobs", "Search", FormMethod.Post, new { id = "searchForm" }))
{
<fieldset>
@Html.LabelFor(m => m.keywords)
@Html.TextBoxFor(m => m.keywords)
@Html.LabelFor(m => m.location)
@Html.TextBoxFor(m => m.location)
@Html.DropDownListFor(m => m.RangeID, new SelectList(Model.Range, "ID", "Range", 5))
<input name="SearchButton" type="submit" value="Search" />
</fieldset>
}
}
<h2>
Jobs</h2>
<div id="resultContainer">
my paged results set will go in here with a link to view job details. I then want
it to come back here and not lose anything
@* html.Action("Results", "Search")*@
@if (Model.SearchResults != null && Model.SearchResults.Count > 0)
{
foreach (var result in Model.SearchResults)
{
<hr />
<table width="100%">
<tr>
<td valign="top">
<div style="font-weight: bold; font-size: large;">
@Html.Raw(@result.Title.Truncate(50))</div>
@Html.Raw(@result.summary.Truncate(50))<br />
</td>
</tr>
</table>
}
<hr />
@Html.PagedListPager(Model.SearchResults, page => Url.Action("Jobs", new RouteValueDictionary() {
{ "Page", page },
{ "Job", Model.Job }
}), PagedListRenderOptions.DefaultPlusFirstAndLast)}
</div>
If the values in the dropdown list won’t change (ever) then you should probably be caching them server side and simply reusing the values each time. You will need to supply the values to the model each time as the data does not persist between successive requests. There is NO viewstate in MVC to retain the values. This is, actually, a good thing.