JamieS
JamieS

Reputation: 307

WebAPI2 attribute based routing 404 with nested route

I know there are lots of (answered) questions relating to attribute-based routing, but I can't seem to find one which answers my particular scenario.

I've got a WebAPI 2 controller, with a few methods using the default routing:

public Dictionary<int, SensorModel> Get()
{
    return SensorModel.List();
}

public SensorModel Get(int id)
{
    return SensorModel.Get(id);
}

[HttpPost]
public SensorModel Post(SensorModel model)
{
    if (model == null) throw new Exception("model cannot be null");
    if (model.Id <= 0) throw new Exception("Id must be set");
    return SensorModel.Update(model.Id, model);
}

These all work fine. I'm trying to create a nested route as below:

[Route("sensor/{id}/suspend")]
public SensorModel Suspend(int id, DateTime restartAt, EnSite site)
{
    return SensorModel.Suspend(id, restartAt, site);
} 

For which I would expect the URL to look like:

http://[application_root]/api/sensor/1/suspend?restartAt={someDateTime}&site={anInt}

Sorry, forgot to say that the actual issue is a 404! Can anyone tell me what I'm doing wrong? I know that I can do it like this:

[Route("sensor/suspend")]
public SensorModel Suspend(int id, DateTime restartAt, EnSite site)
{
    return SensorModel.Suspend(id, restartAt, site);
}

Which makes the URL:

http://[application_root]/api/sensor/suspend?id=1&restartAt={someDateTime}&site={anInt}

But a cleaner API design seems to be a nested route, I think.

Upvotes: 0

Views: 129

Answers (1)

Your assumption is wrong in this point:

For which I would expect the URL to look like:

http://[application_root]/api/sensor/1/suspend?restartAt={someDateTime}&site={anInt}

It should be something like below:

http://[application_root]/sensor/1/suspend?id=1&restartAt={someDateTime}&site={anInt}

When you specify an attribute based routing, it overrides the default routing architecture of ../api/.. (or whatever you specify in route.config file).

So, whenever you try to use attribute based routing, you should do something like /route_prefix_at_controller_level/route_prefix_at_method_level.

Upvotes: 1

Related Questions