How to structure controller to sort multiple criteria asp.net mvc
What's the best way to set up a controller to sort by many (possibly null) criteria? Say for example, I was bu开发者_JAVA技巧ilding a site that sold cars. My CarController has a function Index() which returns an IList of cars to the view, and details on each car are rendered with a partial view.
What's the best way to structure this? Especially if there are a lot of criteria: Car Type (aka SUV), Car Brand, Car Model, Car Year, Car Price, Car Color, bool IsNew, or if I want to sort by closest to me etc... I'm using NHibernate as my ORM. Should I have just a ton of possible NHibernate queries and figure out which one to choose based on if/then's in the controller? Or is there a simpler way.
Thanks so much for the help.
I have tasks in my system and created special class for searching:
public class TaskSearchCriteria
{
public List<int> Statuses { get; set; }
public List<int> Severities { get; set; }
public List<int> CreatedBy { get; set; }
public List<int> ClosedBy { get; set; }
public List<int> LastModificationBy { get; set; }
public DateTime? CreationDateFrom { get; set; }
public DateTime? CreationDateTo { get; set; }
public bool SearchInComments { get; set; }
public bool SearchInContent { get; set; }
public bool SearchInTitle { get; set; }
}
One method in that class applies filters:
public IQueryable<Task> Filter(IQueryable<Task> tasks)
{
return
FilterDates(
FilterAssignedTo(
FilterGroups(
FilterOperationSystems(
FilterPlatforms(
FilterPriorities(
FilterSeverities(
FilterVersionsResolved(
FilterVersionsReported(
FilterTaskContent(
FilterStatuses(tasks)))))))))));
}
This is one of methods used for filtering:
private IQueryable<Task> FilterSeverities(IQueryable<Task> tasks)
{
if (Severities.Contains(TaskSearchConsts.All) || (!Severities.Any()))
return tasks;
var expressions = new List<Expression>();
if (Severities.Contains(TaskSearchConsts.Active))
expressions.Add(_taskParameter.EqualExpression("Severity.IsActive", 1));
return tasks.WhereIn(_taskParameter, "Severity.ID", Severities, expressions);
}
This is Entity Framework, but it can be easily done in nHibernate too by adding where clauses to IQuery.
To search I have a method in controller:
[HttpPost]
public ActionResult TaskSearch([Bind(Prefix = "Search")]TaskSearchCriteria criteria)
Having one class for filtering is nice, because it can be serialized and save to database for future use. This way user can reuse filter parameters.
You would have:
public class CarSearchCriteria
{
List<int> ListOfCarTypesIds;
List<int> ListOfCarBrandIds;
bool IsNew;
//and more
}
If list is empty, you don't apply filter.
If you've got a lot of criteria, I find it best to encapsulate in a class rather than passing in lots of action parameters. For example, a project i'm working on at the moment has an action with the following signature:
public claass JobsController : Controller
{
public IList<JobDto> Index(JobSearchCriteria criteria)
{
IList<JobDto> jobs = _jobs.Find(criteria);
//...
}
}
The repository method simply steps through the criteria building up an IQueryable as it goes along. This particular project uses Linq To Sql but the same principal can apply using NHibernates Criteria API (or Linq to NH).
精彩评论