2

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?

2 Answers 2

1

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.

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

Comments

1

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

Comments

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.