2

Suppose I have this URL:

api.XXX.com/cities?risk=a,b&rating=x,y

What I want is a list of cities with a Risk category of A or B AND a Rating of X or Y. How should I implement this?

I understand I can get the values of the Risk and Rating keys but then what? Is it best to simply parse the string and use a switch statement? Or is there a better approach?

DenaliHardtail
  • 27,362
  • 56
  • 154
  • 233
  • Easiest way is to post the data inside the request body as JSON instead of query strings. – Win Jul 26 '17 at 20:56
  • @Win - I considered that but everything I read points to this being a GET. Plus, it's easier for me to get support if this is a read-only API. Using POST would likely raise some flags and complicate discussions. – DenaliHardtail Jul 26 '17 at 21:00
  • You cannot construct that kind of complex object in query string. – Win Jul 26 '17 at 21:02
  • @Win - I might be missing what you're saying but I have the above example working in code. I'm asking the question because it doesn't feel like a good design. Are you saying it's technically a bad idea, not recommended for REST design or something else? – DenaliHardtail Jul 26 '17 at 21:06
  • I thought you want to post array of cities like this - `[{city: "New York", risk: "a", rating: "x"}, {city: "Chicago", risk: "b", rating: "y"}, {city: "LA", risk: "a", rating: "x"}]` – Win Jul 26 '17 at 21:09
  • @Win - No, this is for passing the criteria to GET a list of cities. – DenaliHardtail Jul 26 '17 at 21:11

2 Answers2

5

A more standard approach would be:

api.XXX.com/cities?risks=a&risks=b&ratings=x&ratings=y

Which could be handled by a controller action something like this:

[HttpGet]
public async Task<IHttpActionResult> SearchCities(
    List<string> risks,
    List<string> ratings)
{
    var results = this.dbContext.Cities.AsQueryable();
    if(risks.Any()) 
    {
        results = results.Where(c => c.Risks.Any(cr => risks.Contains(cr.Code));
    }
    if(ratings.Any())
    {
        results = results.Where(c => ratings.Contains(c.Rating));
    }
    ...
}

Similar answer here.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0

I'd recommend creating a POCO to represent the options that this endpoint will be receiving:

public class CitySearchOptions
{
   public List<string> Risk { get; set; }
   public List<string> Rating { get; set; }
}

You can then use the [FromUri] attribute in your controller signature to have the query string be automatically deserialized into your POCO. From there you can easily implement logic to act on the received values.

public async Task<IHttpActionResult> SearchCities([FromUri] CitySearchOptions options)

Note that the above is psuedo code and might not work for you out of the box without a few tweaks to the format of your query string. This question suggests that for list based query params you should prefer a format like this:

/cities?risk=a&risk=b&rating=x&rating=y
Jesse Carter
  • 20,062
  • 7
  • 64
  • 101