I'm aware of a few ways to handle what I'm trying to do, but I'm I'd like to use the best way. Best being least custom/least code solution. I've got a table on my view and I'm using the JQuery DataTables plugin. I'm using the plugin's feature that allows it to fetch JSON formatted data from the server. When the plugin makes the ajax call to my Action on my controller, it adds a lot of info to the request that I can bind to a model. However, I can't control the keys in the request, so I end up with properties on my model like, 'sSearch_1', 'bSearchable_1', 'bSortable_2', etc...
So, my Action Method looks like this...
public JsonResult CompanyList(JQueryDataTableParamModel param){
var allCompanies = DataRepository.GetCompanies();
IEnumerable<Company> filteredCompanies;
//Check whether the companies should be filtered by keyword
if (!string.IsNullOrEmpty(param.sSearch))
{
//Optionally check whether the columns are searchable at all
var isNameSearchable = param.bSearchable_1; // Convert.ToBoolean(Request["bSearchable_1"]);
var isAddressSearchable = param.bSearchable_2; // Convert.ToBoolean(Request["bSearchable_2"]);
var isTownSearchable = param.bSearchable_3; //Convert.ToBoolean(Request["bSearchable_3"]);
filteredCompanies = DataRepository.GetCompanies()
.Where(c => isNameSearchable && c.Name.ToLower().Contains(param.sSearch.ToLower())
||
isAddressSearchable && c.Address.ToLower().Contains(param.sSearch.ToLower())
||
isTownSearchable && c.Town.ToLower().Contains(param.sSearch.ToLower())).ToList();
}
else
{
filteredCompanies = allCompanies.ToList();
}
var isNameSortable = param.bSortable_1;
var isAddressSortable = param.bSortable_2;
var isTownSortable = param.bSortable_3;
var sortColumnIndex = param.iSortCol_0;
Func<Company, string> orderingFunction = (c => sortColumnIndex == 1 && isNameSortable ? c.Name :
sortColumnIndex == 2 && isAddressSortable ? c.Address :
sortColumnIndex == 3 && isTownSortable ? c.Town :
"");
//var sortDirection = Request["sSortDir_0"]; // asc or desc
filteredCompanies = param.sSortDir_0 == "asc" ? filteredCompanies.OrderBy(orderingFunction).ToList() : filteredCompanies.OrderByDescending(orderingFunction).ToList();
var displayedCompanies = filteredCompanies.Skip(param.iDisplayStart).Take(param.iDisplayLength);
var result = from c in displayedCompanies select new[] { Convert.ToString(c.ID), c.Name, c.Address, c.Town };
return Json(new
{ param.sEcho,
iTotalRecords = allCompanies.Count(),
iTotalDisplayRecords = filteredCompanies.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
public ActionResult Detail() {
return View();
}
}
As you can see in this example, I've got a few places where I've pulled the value from the Model, and set it to a variable of the same type, but with a more meaningful name. While this makes my code more readable, it's redundant. For example:
var isNameSearchable = param.bSearchable_1;
What I would like to do, is create a property on my Model 'IsNameSearchable' and have it bind to the 'bSearchable_1'.
I've come up with these options: 1. I know I can create a custom Model binder that implements IModelBinder, but then I would have to do the complete model binding, and there is a lot of the default model binding that will still work for what I want to do. 2. I could inherit from the DefaultModelBinder, and only override the binding I need to override, and allow the default binding to work as normal in most cases. 3. Leave it they way I have it, auto-binding my model to meaningless values and manually binding to meaningful variables later.