ASP.NET Web API Routing and Actions Notes

2013-12-19


(Note: Here we only provide a learning note, so most sample code below are not ours, for example, most of them were copied from Microsoft ASP.NET website)

1: Similar to MVC routing, ASP.NET Web API uses routing too.

MVC 5 routing:

In the file App_Start/RouteConfig.cs:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
    ); 
}

ASP.NET Web API routing:

In WebAPIConfig.cs file:

routes.MapHttpRoute( 
    name: "API Default", 
    routeTemplate: "api/{controller}/{id}", 
    defaults: new { id = RouteParameter.Optional } 
);

The main difference is that Web API uses the HTTP method, not the URI path, to select the action. You can also use MVC-style routing in Web API.

2: Routing Table:

There is not only one routing can be used in a project, so we have multiple routings and called them routing table.

Each entry in the routing table contains a route template. The default route template for Web API is "api//". In this template, "api" is a literal path segment, and and are placeholder variables.

3: If use default Web API routing, then we must use naming convention for HTTP methods with GET, POST, PUT and DELETE.

for example: We must use:
GetAllProducts to match the URI Path api/products (HTTP Method: GET);
GetProductByID to match the URI api/products/4 (HTTP Method: GET);;
DeleteProduct to match api/products/4 (HTTP Method: DELETE);

If we do not want to be forced to use naming convention for HTTP methods, we can explicitly specify the HTTP method for an action with attributes: HttpGet, HttpPut, HttpPost, HttpDelete:

public class ProductsController : ApiController 
{ 
    [HttpGet] 
    public Product FindProduct(id) {} 
}

AcceptVerbs attribute can take a list of HTTP methods including other methods other than Get, Put, Post and Delete.

public class ProductsController : ApiController 
{ 
    [AcceptVerbs("GET", "HEAD")] 
    public Product FindProduct(id) { }

    // WebDAV method 
    [AcceptVerbs("MKCOL")] 
    public void MakeCollection() { } 
}

4: If self-host Web API, then no WebApiConfig.cs file, we must set the routing table directly on the HttpSelfHostConfiguration object;

5: Routing By Action Name:

We set the routing as this:

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

Then with this routing, we can specify which one action method we like in Controller as HTTP method using Http attributes, for example:

public class DevicesController : ApiController 
{ 
    [HttpGet] 
    [ActionName("DeviceValue")] 
    public double GenerateDeviceValue(int id); 
}

Non-Actions:

Use [NonAction] attribute to prevent a public method from getting invoked as an action.

6: To provide your own implementation for any of these interfaces, use the Services collection on the HttpConfiguration object:

var config = GlobalConfiguration.Configuration; 
config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config));

7: constraints:

new { id = @"\d+" }   // Only matches if "id" is one or more digits. 

see here.

8: ASP.NET Web API released 2 versions by now: ASP.NET Web API and ASP.NET Web API 2; Web API 2 supports new Attribute Routing and earlier style of routing called Convention-Based Routing, Web API only supports Convention-Based Routing;

9: Combine attribute routing with convention-based routing:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
// �> enable attribute routing 
        config.MapHttpAttributeRoutes();

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

10: Sample of attribute routing:

RoutePrefix("api/books")]  // <� route prefix 
public class BooksController : ApiController 
{ 
    // GET api/books 
    [Route("")] 
    public IEnumerable<Book> Get() { � }

    // GET api/books/5 
    [Route("{id:int}")] 
    public Book Get(int id) { � }

    // POST api/books 
    [Route("")] 
    public HttpResponseMessage Post(Book book) { � } 

// Use a tilde (~) on the method attribute to override the route prefix: 
    // GET /api/authors/1/books 
    [Route("~/api/authors/{authorId:int}/books")] 
    public IEnumerable<Book> GetByAuthor(int authorId) { � }

}