Mykhailo Seniutovych
Mykhailo Seniutovych

Reputation: 3711

How to send controller action in url parameter in Asp.net Web Api?

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

Answers (2)

Mykhailo Seniutovych
Mykhailo Seniutovych

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

becnelli
becnelli

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

Related Questions