Matthew Knudsen
Matthew Knudsen

Reputation: 213

MVC 4 Web API Routing issues

This is my first rodeo with MVC Web API and I'm having some issues understanding the routing aspects. I would like to have a uri template similar to thise:

  1. http://google.com/api/AzureQueue - GET for all items in the queue
  2. http://google.com/api/AzureQueue/DeviceChart/ - GET returns devices and processing time for agent

http://google.com/api/{controller}/{id} <-- default http://google.com/api/{controller}/{chartType}/{id} where ID is optional

where I'm struggling is: 1. what the french toash do I put in the WebApiConfig.cs file 2. do I need to do anthing special in my controller eg. specifiy NonActions & Actions, Action Names, etc

Any help is appreciated

Upvotes: 2

Views: 1408

Answers (1)

Christopher Stevenson
Christopher Stevenson

Reputation: 2871

You are almost there. The default route (in WebApiConfig.cs looks like this:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

There's one very important caveat: the routes are examined in the order that they are declared with the first matching one being used, so the default route needs to go last.

With that out of the way, you need to make a decision, do you want the calls for various chart types to go to one action, or many?

For one action:

WebApiConfig.cs

        config.Routes.MapHttpRoute(
            name: "AzureQueue",
            routeTemplate: "api/AzureQueue/{chartType}/{id}",
            defaults: new { controller = "AzureQueue", id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

AzureQueueController.cs

public class AzureQueueController : ApiController
{
    public string Get(string chartType)
    {
        return "chart = " + chartType;
    }
    public string Get(string chartType, int id)
    {
        return "chart = " + chartType + ",id = " + id.ToString(); 
    }
}

There are two things to notice here. In the anonymous class assigned to defaults, the value for controller decides which controller to route the request to. This can either be in the route template, or simply defined in the class. Also, a request of type Get is automatically sent to an action that starts with Get and has the arguments in the Url that match the template (there are two different cases since id is optional).

This would be my preferred way to go unless the business logic for various charts is different.

On the other hand you could specify this:

WebApiConfig.cs

        config.Routes.MapHttpRoute(
            name: "AzureQueue",
            routeTemplate: "api/AzureQueue/{action}/{id}",
            defaults: new { controller = "AzureQueue", id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

Since I'm using the word action is the template, this will get interpreted as an action name.

AzureQueueController.cs

    [HttpGet]
    public string DeviceChart()
    {
        return "chart = DeviceChart" ;
    }

    [HttpGet]
    public string DeviceChart(int id)
    {
        return "chart = DeviceChart" + ",id = " + id.ToString(); 
    }

Here there is no string argument, that part of the url is being used to decide which action (public method) to use. Also, since the action names don't start with Get, I need to add an attribute [HttpGet] for each method to mark them as being able to receive GET requests.

Good luck with your project.

Upvotes: 1

Related Questions