简体   繁体   中英

API multiple Get methods and routing

I have a controller with only Get Methods

public class DeviceController : ApiController
{
    List<Device> machines = new List<Device>();

    public IEnumerable<Device> GetAllMachines()
    {
        //do something
        return machines;
    }

    [HttpGet]
    public IEnumerable<Device> GetMachineByID(int id)
    {
        //do something
        return machines;
    }

    [HttpGet]
    public IEnumerable<Device> GetMachinesByKey(string key)
    {
        //do something
        return machines;
    }

}

I would like to be able to access these via URL and get the data back

../api/{contorller}/GetAllMachines
../api/{contorller}/GetMachineByID/1001
../api/{contorller}/GetMachiesByKey/HP (machines exist)

When i run the first two in IE developer mode (f12) i get Json back displaying all machines and machine 1001. However when i run GetMachinesByKey/HP i get 404 error.

Also my WebApiConfig looks like this

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{Action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Anyone enlighten me as to what I am doing wrong?

The routing engine is expecting to bind to a variable named id as defined in the route config:

config.Routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{Action}/{id}", //<--- here {id} means bind to parameter named 'id'
    defaults: new { id = RouteParameter.Optional }
);

In your action GetMachinesByKey(string key) parameter is named key and so the framework isn't connecting those dots for you.

You could pass the parameter in the querystring so using a URL of the form /api/{contorller}/GetMachiesByKey/?key=HP will bind correctly (you may need to change the route config as this doesn't pass an id parameter that the current config will be expecting).

Alternatively I believe you can specify a route for an action using attribute routing . This allows you to decorate your action method with an attribute which tells the framework how the route should be resolved eg:

[Route("<controller>/GetMachinesByKey/{key}")]
public IEnumerable<Device> GetMachinesByKey(string key)

Use the RoutePrefix and Route attributes.

[RoutePrefix("api/device")]
public class DeviceController : ApiController
{
List<Device> machines = new List<Device>();

[HttpGet]
[Route("Machines")]
public IEnumerable<Device> GetAllMachines()
{
    //do something
    return machines;
}

[HttpGet]
[Route("Machines/{id:int}")]
public IEnumerable<Device> GetMachineByID(int id)
{
    //do something
    return machines;
}

[HttpGet]
[Route("Machines/{key}")]
public IEnumerable<Device> GetMachinesByKey(string key)
{
    //do something
    return machines;
}

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