On my page I have:
Searching works OK - I can input some text or check a checkbox in the filter section and the appropriate results are displayed.
Paging works OK only if I use it when the page is loaded (that means before I click Search button, in this case the url is '...Home').
But if click search first (in this case the url will become '...Home/Search') and then try to go to another page on the grid then I get an exception in the Search method, because the model.Filter parameter is null (System.NullReferenceException: Object reference not set to an instance of an object.)
I tried to solve the problem in many different ways (with RedirectToAction method, storing the filter to session and use it in Search method,...) but no solution worked in all scenarios. Any ideas?
My simplified code:
HomeController:
public ActionResult Index()
{
// On page load display all data without filters.
var filter = new OverviewFilterModel
{
Type1 = true,
Type2 = true,
WorkingOrder = ""
};
ViewBag.Results = GetResults(filter);
return View(new HomeModel { Filter = filter });
}
public ActionResult Search(HomeModel model)
{
ViewBag.Results = GetResults(model.Filter);
return View("Index");
}
public class OverviewFilterModel
{
public bool Type1 { get; set; }
public bool Type2 { get; set; }
public string WorkingOrder { get; set; }
}
public class HomeModel
{
public OverviewFilterModel Filter { get; set; }
public IEnumerable<OverviewResultsModel> Results { get; set; }
}
View:
<!-- ... -->
@model HomeModel
<!-- ... -->
@using (Html.BeginForm("Search", "Home", FormMethod.Post, new { @class = "form-inline" }))
{
<div class="form-group" style="margin-left: 135px;">
@Html.CheckBoxFor(p => p.Filter.Type1)@Html.LabelFor(p => p.Filter.Type1, new { style = "margin: 0 15px 0 5px;" })
</div>
<!-- a bunch of other checkboxes -->
<br />
<div class="form-group">
<label style="width: 130px; text-align: right;">Delovni nalog</label>
@Html.TextBoxFor(p => p.Filter.WorkingOrder, new { @class = "form-control ecert-filter-small", @autocomplete = "off" })
</div>
<!-- a bunch of other textboxes -->
<button class="k-button" id="button-refresh" style="margin: 10px 0 0 135px;">Refresh</button>
<hr />
@(Html.Kendo().Grid<OverviewResultsModel>()
.BindTo((IEnumerable<OverviewResultsModel>)ViewBag.Results)
.Name("gridOverview")
.Events(p => p.Change("overviewOnRowSelect"))
.Columns(columns =>
{
columns.Template(@<text>@Html.ActionLink("WorkingOrder", "Index", "WO", new { dn = @item.WorkingOrder }, new { @class = "selectable-dn" })</text>).Title("");
columns.Bound(p => p.Type);
columns.Bound(p => p.WorkingOrder);
columns.Bound(p => p.Date);
columns.Bound(p => p.ProductId);
columns.Bound(p => p.ProductName);
})
.Selectable()
.Pageable(p => p
.Refresh(true)
.PageSizes(true)
.ButtonCount(10)
.Messages(q =>
{
q.Display("{0} - {1} od {2} records");
q.Empty("No data for selected filter");
q.ItemsPerPage("Number of records per page");
})
)
.DataSource(p => p.Server().PageSize(20).Model(q => { q.Id(r => r.WorkingOrder); }))
)
}
I solved this with the help of session objects - one for filter and one for result. Not the most elegant solution but it works.
public ActionResult Index()
{
// On page load display all data without filters.
OverviewFilterModel filter;
if (Session["filter"] == null) {
var filter = new OverviewFilterModel
{
Type1 = true,
Type2 = true,
WorkingOrder = ""
};
}
else {
filter = (OverviewFilterModel)Session["filter"];
}
if (Session["results"] == null){
ViewBag.Results = GetResults(filter);
}
else{
ViewBag.Results = Session["results"];
}
return View(new HomeModel { Filter = filter });
}
public ActionResult Search(HomeModel model)
{
if (model.Filter == null)
{
model.Filter = (OverviewFilterModel)Session["filter"];
}
ViewBag.Results = GetResults(model.Filter);
return View("Index");
}
private IEnumerable<OverviewResultModel> GetResults(OverviewFilterModel filter){
var data = ...
Session["results"] = data;
Session["filter"] = filter;
return data;
}
Probably this way helps by handle null value of HomeModel.Filter in Search method before executing GetResults(model.Filter)
:
public ActionResult Search(HomeModel model)
{
if (model.Filter == null)
{
model.Filter = new OverviewFilterModel
{
Type1 = true,
Type2 = true,
WorkingOrder = ""
};
}
ViewBag.Results = GetResults(model.Filter);
return View("Index", new HomeModel { Filter = filter });
}
I just figured that null value should be handled by an if-condition to prevent NRE, CMIIW.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With