简体   繁体   中英

What is the best way to filter a list of database records that can only be filtered through javascript in ASP.NET MVC

Question:

Suppose I have a list of database records in ASP.NET MVC Web Application. What is the best way to filter this list by a criteria that can only be filtered through Javascript?

If my question is not clear, Please see the example below.

Example:

I have a controller action that returns all or portion of my restaurants in the database and in its view I'm showing all these restaurants:

public ActionResult Index()
{            
    return View(restaurantRepository.GetAll());
}

Now each restaurant has a service boundary which is a polygon and i'm storing this polygon in the database through the following model property:

public class Restaurant
{
      // Other properties omitted...

      public ICollection<Coordinate> Coordinates { get; set; }
}

Coordinates is basically a collection of Latitude/Longitude objects representing a polygon.

Now i want the functionality that if i give Index action a point in the map (Latitude/Longitude), then Index action should only return the restaurants which contain this point in their service boundary (polygon).

Now obviously I can't do this filtering in the controller because drawing polygons and checking if a point exists in them are only done through Google Maps API and Javascript.

Edit: Thanks to the suggestion by @amg-argh i searched a bit to see if i can check whether a point is inside a polygon only with C/C# and i found this post which works. Nevertheless my question remains.

What would be the best way to achieve this filtering through Javascript?

My Own Thoughts:

What came to my mind was to

  • First return all the restaurants to the view.
  • Then in the view I deserialize my model with

    var model = @Html.Raw(@JsonConvert.SerializeObject(Model, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }));

  • Then iterate through my model with forEach and extract the restraurants that have that criteria met.

     model.forEach(function(restaurant){ if(checkBoundaries(restaurant, latLng)) { // Valid restaurant. Save the id in an array. } else { // Invalid restaurant. discard it. } }); 
  • Then send the valid restaurants array with an AJAX post request to a controller action that returns the restaurants for the given restaurant Ids.

But these all seem like a lot of work and a bad practice. Any ideas?

This question might actually be suited to another stackexchange site, as it's more about program design than actual implementation. Nevertheless, to achieve this on the Frontend rather than the backend.

  1. Load your view via the Index method, this view should really only contain stub HTML and basic elements that you need for your view. Think headers, footers, titles etc (and potentially a FrontEnd template)
  2. Load your list of restaurants via AJAX, using WebApi. So move return View(restaurantRepository.GetAll()); into web api and do something like return Ok(restaurantRespostory.GetAll()) .
  3. Iterate through the result, when if(checkBoundaries(restaurant, latLng)) passes, add an HTML Element / Marker to the map / whatever view you are trying to display to your view, using JavaScript. When it fails, ignore it, do nothing.

That's basically all you want to do, and will save you a postback and a second round trip to the server.

Though I would suggest a few other changes too

  1. Use a frontend MVVM/MVC framework (angularjs, react, knockout, etc), to render your results via JavaScript. Filter your array and have it bound to the view with something like myViewVariable.inBoundryRestraunts = model.filter(function(r){ return checkBoundaries(r, latLng);}) . It is much tidier to do it this way, rather than creating a bunch of HTMLElement on the fly.
  2. Find someway (that doesn't need to be perfect) to limit the results from the backend still. Although I don't know the specific details of your application I can imagine that an average sized city will have thousands if not tens of thousands of restaurants. Downloading all this data to be processed on the frontend will take a long time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM