Dan Cook
Dan Cook

Reputation: 2072

Web API route for different parameter types

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?

Upvotes: 0

Views: 1904

Answers (1)

Sam Axe
Sam Axe

Reputation: 33738

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

Upvotes: 2

Related Questions