0

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.

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Okay, that makes sense that if I lose the leading "/api" it shoudl work - but the route still isn't properly nested if I have to include the "id" parameter in the query string, what I'd like is for it to be pulled from earlier in the URL, as things like angular-ui-router do - any ideas?
@JamieS: I Believe, you are looking in to kind of like this: [Route("sensor/suspend/{id}/{someDateTime}/{int}")]. Modify your routes like this and beware: Only when every thing (id, datetime, int) is present, this route will be matched. All fields are compulsary.
Ah okay, so there's no way with WebAPI routing to have the pattern be "sensor/{id}/suspend/{someDateTime}/{int}" ?
@JamieS: I meant it is valid to do so & it is perfectly possible, but all the items [id, someDateTime, int] must be supplied in the Url.
that's fine, just to confirm, as my URL and yours are different: the parameters don't have to all be at the end of the URL, the "id" one can be in between 2 other elements as I have it?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.