2

In my controller UserApiController, I have the following functions:

public object GetUsers(string CountryID, string StateID)
{
   //biz
}

public object GetPositions(int CompanyID, int DepartmentID)
{
   //biz
}

In my controller SalesApiController, I have the following functions:

public object GetOrders(string CountryID, int CompanyID)
{
   //biz
}

public object GetProducts(string CountrID, string StateID, int CompanyID)
{
   //biz
}

in the web api config, I can map like this:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}",
    defaults: new {  }

and it works for UserApiController.GetUsers as the function signature only matches with GetUsers.

now, questions:

1.how to define a route to handle different functions with same amount of parameters (either within same or different controller)

2.how to define a route to handle different functions with different amount of parameters (either within same or different controller, if possible)

2
  • 1
    Since this is webapi, why worry about route parameters? Why not just use plain old querystring parameters? Commented Oct 3, 2012 at 15:24
  • yes and no, we can use old school query string, yet, it's better to stick to rest since that's the nature of web api :) Commented Oct 3, 2012 at 23:01

2 Answers 2

3

1.how to define a route to handle different functions with same amount of parameters (either within same or different controller)

There are several solutions here.

  • Use multiple routes. Take your UserApiController as an example, it is hard to have one route that works with the 2 actions, in which they have different parameter names. I would suggest add the following 2 routes:

        config.Routes.MapHttpRoute(
            name: "DefaultApi-UserApiGetUsers",
            routeTemplate: "api/{controller}/GetUsers/{CountryID}/{StateID}",
            defaults: new { action = "GetUsers" });
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi-UserApiGetPositions",
            routeTemplate: "api/{controller}/GetPositions/{CompanyID}/{DepartmentID}",
            defaults: new { action = "GetPositions" });
    
  • Use query string parameters as danludwig has suggested. This way, you only need this one route:

        config.Routes.MapHttpRoute(
            name: "DefaultApiOnlyRoute",
            routeTemplate: "api/{controller}/{action}");
    
    1. api/UserApi/GetUsers?CountryID=USA&StateID=WA
    2. api/UserApi/GetPositions?CompanyID=123&DepartmentID=456

2.how to define a route to handle different functions with different amount of parameters (either within same or different controller, if possible)

  • Again, define multiple routes:

        config.Routes.MapHttpRoute(
            name: "DefaultApi-SalesApi2Params",
            routeTemplate: "api/{controller}/{action}/{CountryID}/{CompanyID}");
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi-SalesApi3Params",
            routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}/{CompanyID}");
    
  • Use query string parameters instead and have only one route -- i.e. the 'DefaultApiOnlyRoute' from above.

    1. api/SalesApi/GetOrders?CountryID=USA&CompanyID=123
    2. api/SalesApi/GetProducts?CountryID=USA&StateID=WA&CompanyID=123

Hope this helps.

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

2 Comments

hi, regarding the query string, we know it should work. talking about web api routing, i know we can define route for each action respectively, but just imagine there are tons of functions and I don't believe we can afford the time.
There are some 3rd party nuget packages such as AttributeRouting that you can look into.
2

You can create an attribute like this one and then decorate your actions with this attribute. You still need to create a route like the one you did that matches the number of parameters.

public class SomeAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    for(int i = 0; i <= filterContext.ActionParameters.Count; i++)
    {
      // i + 2 is to not consider controller and action parameters
      filterContext.ActionParameters[filterContext.ActionParameters.ElementAt(i).Key] = 
        Convert.ChangeType(
          filterContext.Controller.ControllerContext.RouteData.Values.ElementAt(i + 2).Value, 
          filterContext.ActionDescriptor.GetParameters()[i].ParameterType
        );
      }
   }
}

I hope it helps.

7 Comments

as I can infer from the code that you are dynamically setting the parameter values. but will it work even the name of the parameter is not same, like the two functions in UserApiController with only ONE route mapped?
Yes, it will. I created exactly the same controller to test it before posting. It works with SalesApiController.GetOrders action as well.
sorry, i am still facing 404 error, could you please post your web api route mapping as well?
This is route mapping: routes.MapHttpRoute( name: "TwoParametersGenericRoute", routeTemplate: "api/{controller}/{action}/{CountryID}/{StateID}");
All of these urls have worked: api/UserApi/GetPositions/55/1, api/UserApi/GetUsers/55/1, api/Sales/GetOrders/55/1
|

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.