Reputation: 3711
Typically you call an action of a controller like so http://hostname/MyController/MyAction
I have a requirement for my Web Api to have routes like this one:
http://hostname/MyController?action=MyAction
, i.e., pass the action in url parameter.
My controller:
public class MyController : ApiController
{
[HttpGet]
[Route("WHAT SHOULD BE HERE??")]
public IHttpActionResult MyAction()
{
// some code
}
}
Any ideas how I can write such a routing?
Upvotes: 2
Views: 909
Reputation: 3711
After more than a year I can come back to this question and answer it myself.
The solution you can use here is to write your own ActionSelector - this is the class Web Api framework uses to select actions, by default it uses System.Web.Http.Controllers.ApiControllerActionSelector
, which you can override.
So lets say your controller looks like this:
public class MyController : ApiController
{
[HttpGet]
public IHttpActionResult MyAction()
{
// some code
}
}
Then you can create your own action selector like this (the code might be improved I wrote it very quickly):
public class QueryParameterActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var mapping = GetActionMapping(controllerContext.ControllerDescriptor);
var parameters = controllerContext.Request.GetQueryNameValuePairs();
foreach (var parameter in parameters)
{
if (parameter.Key == "action")
{
if (mapping.Contains(parameter.Value))
{
// Provided that all of your actions have unique names.
// Otherwise mapping[parameter.Value] will return multiple actions and you will have to match by the method parameters.
return mapping[parameter.Value].First();
}
}
}
return null;
}
}
And then finally you have to register this action selector in WebApiConfig.Register
method. It will look like this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}"
);
config.Services.Replace(typeof(IHttpActionSelector), new QueryParameterActionSelector());
}
}
Now you can call your action like this http://hostname/controller?action=MyAction
Upvotes: 1
Reputation: 163
You could try the following:
public class MyController : ApiController
{
[HttpGet]
[Route("MyController")]
public IHttpActionResult MyInnerController(String action)
{
switch(action)
{
case "MyAction":
return MyAction();
}
return BadRequest("Invalid action: " + action);
}
public IHttpActionResult MyAction()
{
return Ok();
}
}
Things will get more complicated if you require additional parameters.
Upvotes: 1