0

Trying to get my head around Web API routing.

I have the following two controllers which have different methods/actions

 public class MerchantController : ApiController
    {
        [HttpGet]
        [ActionName("GetSuggestedMerchants")]
        public IEnumerable<Merchant> GetSuggestedMerchants(string name)
        {
           ....

and

    public class PortalMerchantController : ApiController
    {
        [HttpGet]
        [ActionName("GetNPortalMerchants")]
        public IEnumerable<PortalMerchantDto> GetNPortalMerchants(int id)
        {
          ...

And I have these two routes mapped:

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

Calling

$http.get("api/PortalMerchant/GetNPortalMerchants/26") 

works fine but calling

$http.get("api/Merchant/GetSuggestedMerchants/SomeName")

does not get routed and fails with:

{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:2769/api/Merchant/GetSuggestedMerchants/SomeName'.","MessageDetail":"No action was found on the controller 'Merchant' that matches the request."}

I figured I needed two roots because the parameter name and type is different for the two methods. Can anyone suggest why the second one does not get routed?

halfer
  • 19,824
  • 17
  • 99
  • 186
Dan Cook
  • 1,935
  • 7
  • 26
  • 50
  • I guess it must be using the first route $http.get("api/Merchant/GetSuggestedMerchants/SomeName") which would explain why no action was found on the Merchant controller (as there is no method which takes an ID parameter) but why would it use the first route and not the second when the parameter names are specified? – Dan Cook Dec 01 '13 at 01:41

1 Answers1

2

Routing take the first route that matches the URL.

Your URLs do not contain named parameters.. just parameter values.

You need to define stricter routeTemplates. Like:

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

The order of the routes matters

Sam Axe
  • 33,313
  • 9
  • 55
  • 89