I'm using the final release versions of .NET 4.5 and Web API 2 (in Visual Studio 2013). I've been using this documentation as a reference, to no avail.
I have a few base routes like
api/providers
api/locations
api/specialties
And some methods on each like
Get()
Get(int id)
Get(string keyword)
Autocomplete(string keyword)
Search(string zipcode, string name, int radius, [...])
Ideally, I'd like the URLs to end up like
- /api/locations/12345 (get location 12345)
- /api/locations/clinical (get locations with "clinical" in the name)
- /api/locations/autocomplete?keyword=clinical (get a condensed Id + Name object for locations with "clinical" in the name)
- /api/locations/search?zipcode=12345&radius=20&name=clinical (get locations within 20 miles of zip 12345 with "clinical" in the name)
In the chunk of code below, the Get methods and Search work as desired, but Autocomplete does not. It should be noted I have similarly named methods in multiple controllers. What am I doing wrong? (Also, what exactly is the Name = property for?)
/// <summary>
/// This is the API used to interact with location information.
/// </summary>
[RoutePrefix("api/locations")]
public class LocationController : ApiController
{
private ProviderEntities db = new ProviderEntities();
private static readonly Expression<Func<Location, LocationAutocompleteDto>> AsLocationAutocompleteDto =
x => new LocationAutocompleteDto
{
Id = x.Id,
Name = x.Name
};
/// <summary>
/// Get ALL locations.
/// </summary>
[Route("")]
public IQueryable<Location> Get()
{
return db.Locations.AsQueryable();
}
/// <summary>
/// Get a specific location.
/// </summary>
/// <param name="id">The ID of a particular location.</param>
[Route("{id:int}")]
public IQueryable<Location> Get(int id)
{
return db.Locations.Where(l => l.Id == id);
}
/// <summary>
/// Get all locations that contain a keyword.
/// </summary>
/// <param name="keyword">The keyword to search for in a location name.</param>
[Route("{keyword:alpha}")]
public IQueryable<Location> Get(string keyword)
{
return db.Locations.Where(l => l.Name.Contains(keyword)).OrderBy(l => l.Name);
}
[Route("search", Name = "locationsearch")]
public string Search(string zipcode = null, string latitude = null, string longitude = null)
{
if (zipcode != null) return "zipcode";
if (latitude != null && longitude != null) return "lat/long";
else
return "invalid search";
}
/// <summary>
/// Autocomplete service for locations, returns simple Id/Name pairs.
/// </summary>
/// <param name="keyword">The keyword to search on.</param>
[Route("autocomplete/{keyword:alpha}", Name = "locationautocomplete")]
public IQueryable<LocationAutocompleteDto> Autocomplete(string keyword)
{
// validate the inputs
if (string.IsNullOrEmpty(keyword))
return null;
IQueryable<Location> results = from l in db.Locations
where l.Name.Contains(keyword)
select l;
return results.Select(AsLocationAutocompleteDto);
}
There does not seem to be a lot of community support around the latest versions of this stuff yet.
EDIT (with answer)
Simply replaced
[Route("autocomplete/{keyword:alpha}", Name = "locationautocomplete")]
with
[Route("autocomplete"), Route("autocomplete/{keyword:alpha}", HttpGet()]
and it works perfectly.