0

Ok this is something I like to discuss. We have routes like:

.../browse
.../brand/audi/a4
.../category/tail-lights-17
.../search?t=fog+lamp

My current solution is to write different actions and views for these routes. All views are listing products with a partial view but there are some differences like filtering or car selection (which I presume I can handle this again with another partial view)

@if(Model.ShowCarSelection)
{
  @Html.Partial("_CarSelection")
}

I wonder how do you handle scenarios like this. For example what about something like this:

[HttpGet, Route("browse"), Route("/{make}/{model}"), Route("categorySlug")]
public ActionResult List(string make, string model, string categorySlug, int page = 1, string sort, string filter)
{
  var listVM = new ListVM();
  if(!string.IsNullOrEmpty(categorySlug))
    listVM.Products = productService.GetByCategorySlug(categorySlug);
  else if (!string.IsNullOrEmpty(make))
    listVM.Products = productService.GetByMakeAndModel(make, model);
  // other things like filtering, sorting, preparing car selection partial view model etc.
  return View();
}

But this will make a really long action which I will make me feel sad(bad).

Anyone dealt with something like this can give me directions ?

0

1 Answer 1

1

Create a model and pass that to your view and your view will post it back to your controller.

public class SearchCriteria
{
    public string Name { get; set; }
    public string Model { get; set; }
    public string CategorySlug { get; set; }
    public int Page { get; set; }
    public string Sort { get; set; }
    public string Filter { get; set; }
}

And your controller:

public ActionResult List(SearchCriteria searchCriteria)
{
    // Let your service make the decision based on searchCriteria
    productService.Get(searchCriteria);

    // rest of your code
}

Better yet do this so you can use the model for other searches as well:

public abstract class SearchCriteria
{
    public int Page { get; set; }
    public string Sort { get; set; }
    public string Filter { get; set; }
}

public class CarSearchCriteria : SearchCriteria
{
    public string Name { get; set; }
    public string Model { get; set; }
    public string CategorySlug { get; set; }
}

EDIT

In the comment the OP asked the following:

Can I bind url segments to view model?

To clarify the question: If there are items in the querystring and the action method is expecting a complex type, will it pick up the items from the querystring and somehow create the model the action is expecting?

YES. When the DefaultModelBinder class encounters an action method with complex type(s) as parameter(s), it will use reflection to obtain the public properties of the complex type. Then it will use each property's name and look for a match in the following places in the order below. Imagin it was looking for the property name "id":

  1. Request.Form[] array, i.e. Request.Form["id"]
  2. RouteData.Values[] array, i.e. RouteData.Values["id"]
  3. Request.QueryString[] array, i.e. Request.QueryString["id"]
  4. Request.Files[] array, i.e. Request.Files["id"]

Once it has found a match, it will use that value and search no further. So if your form has "id" and the querystring has "id", it will use the one from your form. It will search for every property in those locations. If your model has a complex property, then it will do the same for that.

Sign up to request clarification or add additional context in comments.

1 Comment

This look fine for filtering or search form, i can make a POST request with the SearchCriteria model, But how will I generate and handle category menu links or specific make/model links ? Can I bind url segments to view model ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.