4

I've been struggling with my routing for some time now and after a few days of trying to Google the solution without luck, I'm hoping someone may be able to shine some light on my problem.

I have the following routes in my WebApiConfig:

        config.Routes.MapHttpRoute(
            name: "AccountStuffId",
            routeTemplate: "api/Account/{action}/{Id}",
            defaults: new { controller = "Account", Id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "AccountStuffAlias",
            routeTemplate: "api/Account/{action}/{Alias}",
            defaults: new { controller = "Account", Alias = RouteParameter.Optional }
        );

and the following controller methods:

    [HttpGet]
    public Account GetAccountById(string Id)
    {
        return null;
    }

    [HttpGet]
    public Account GetAccountByAlias(string alias)
    {
        return null;
    }

If I call: /API/Account/GetAccountById/stuff then it properly calls GetAccountById.

But if I call /API/Account/GetAccountByAlias/stuff then nothing happens.

Clearly order matters here because if I switch my declarations of my routes in my WebApiConfig, then /API/Account/GetAccountByAlias/stuff properly calls GetAccountByAlias, and /API/Account/GetAccountById/stuff does nothing.

The two [HttpGet] decorations are part of what I found on Google, but they don't seem to resolve the issue.

Any thoughts? Am I doing anything obviously wrong?

Edit:

When the route fails, the page displays the following:

<Error>
    <Message>
        No HTTP resource was found that matches the request URI 'http://localhost:6221/API/Account/GetAccountByAlias/stuff'.
    </Message>
    <MessageDetail>
        No action was found on the controller 'Account' that matches the request.
    </MessageDetail>
</Error>
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
Mike
  • 199
  • 1
  • 2
  • 9

2 Answers2

6

You should be able to just have the following route:

config.Routes.MapHttpRoute(
        name: "AccountStuffId",
        routeTemplate: "api/Account/{action}/{Id}",
        defaults: new { controller = "Account", Id = RouteParameter.Optional }
    );

and do the following for your actions:

[HttpGet]
public Account GetAccountById(string Id)
{
    return null;
}

[HttpGet]
public Account GetAccountByAlias([FromUri(Name="id")]string alias)
{
    return null;
}
Kiran
  • 56,921
  • 15
  • 176
  • 161
  • That's excellent! I had no idea `[FromUri(Name="id")]` existed. Would you be able to elaborate on it a little? Or even provide a link where I could read up? – Mike Aug 02 '13 at 20:16
  • The attributes, `FromUri` and `FromBody`, tell Web API 2 where to parse out the parameters. In the case of `FromUri`, it will parse out the query string and get the respective named values. – Cameron Tinker Aug 03 '14 at 04:38
1

Is there a reason you need to be declaring two different routes?

Look at the guide at: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

They have one default route and going by the example all you need in your config is

routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
krilovich
  • 3,475
  • 1
  • 23
  • 33