Search code examples
c#asp.net-mvc-4asp.net-web-apiasp.net-web-api-routing

Possible to have a WebAPI method exposed (Get or Post) that can be called like an Action?


That's probably not horribly clear so let me elaborate:

As I currently know, the "action" of the web api controller is determined by the number and types of parameters. So if you pass in two strings, you'll get the Get or Post that has two strings in the method signature.

What I'd like to do is set up several routes like this:

config.Routes.MapHttpRoute(
    name: "fileFunctionsDelete",
    routeTemplate: "api/{controller}/{appName}/{userID}/Delete",
    defaults: new {
        appName = RouteParameter.Optional,
        userID= RouteParameter.Optional,
        fileAction= RouteParameter.Optional
    }
);

config.Routes.MapHttpRoute(
    name: "fileFunctionsUpload",
    routeTemplate: "api/{controller}/{appName}/{userID}/Upload",
    defaults: new {
        appName = RouteParameter.Optional,
        userID= RouteParameter.Optional,
        fileAction= RouteParameter.Optional
    }
);

These should obviously go to the same controller but in an MVC website, I'd go to an action named "Delete" or "Upload".

So far, all I see are Gets and Posts with the number and type of params being used to determine what is called. That's just too confusing.

Is there any way to make it more "MVC website"-like in call behavior?


To clarify: If I want a specific action to fire, I call it by name. "public ActionResult ThisAction(object[] params). In the web api, all the sigatures are like Get or Put or Post. I want to be able to say something like "url:../Delete" and it calls the appropriate delete get or post. I don't want to have to differentiate my methods by the number of parameters I pass in or parse a string to see what the user intended. Those are recipes for failure

UPDATE:

The answers by Kenneth, lgor, and Tu Hoang all have critical information that needs to be taken together (constraining the method for the route, action, model properties, etc) and each have information that makes a complete answer. I can't mark them all so I'm marking the "most correct" for my question.


Solution

  • Personally, I find attribute routing to be a bit easier to work with when you want custom routes on your actions. As exemplified on the official ASP.NET website, you can apply routes directly to your actions using the [Route] attribute:

    e.g.

    public class CustomerController : ApiController
    {
        [Route("api/Customer/{model.LastName}/{model.FirstName}/Upload")]
        public void Post(CustomerModel model)
        {
             // ...
        }
    }
    

    I can't recall if you can substitute in {controller} the way you can in the default routes, but I believe you can. I've got a complex object coming in as the parameter, hence the dot notation, but if you're just using simply types, then you can use the variable names directly (e.g. [Route("api/Customer/{lastName}/{firstName}/Upload")]).

    There's also the [RoutePrefix] attribute which you can apply to the controller so that you don't have to repeat api/Customer/, for example, on every action:

    [RoutePrefix("api/Customer")]
    public class CustomerController : ApiController
    {
        [Route("{model.LastName}/{model.FirstName}/Upload")]
        public void Post(CustomerModel model)
    

    This isn't a terribly good example since I'm demonstrating a POST and the parameters are coming via the URL, but it should demonstrate the idea.