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?

1
  • 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? Commented Dec 1, 2013 at 1:41

1 Answer 1

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

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

1 Comment

You might also look at attribute routing for this scenario.

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.