ASP.NET Web API: CORS support and Attribute Based Routing Improvements

We’ve seen a huge adoption of ASP.NET Web API since its initial release.  In February we shipped the ASP.NET and Web Tools 2012.2 Update – which added a number of additional enhancements to both Web API and the other components of ASP.NET. 

The ASP.NET Team has been hard at work on developing the next set of features (lots of cool stuff coming).  One of the great things about this work has been how the team has used the open source development process – which we announced we were adopting last spring - to collaborate even more closely with the community to both validate the features early, as well as enable developers in the community to directly contribute to the development of them.

Below are some updates on two of the great features coming to ASP.NET Web API – which were developed and contributed by ASP.NET MVP Brock Allen and Tim McCall (of attributerouting.net fame):

CORS support for ASP.NET Web API

Cross-origin resource sharing (CORS) is a W3C standard that allows web pages to make AJAX requests to a different domain. This standard relaxes the same-origin policy implemented in web browsers that restricts calls to the domain of the resource that makes the call. The CORS specification defines how the browser and server interact to make cross-origin calls.

The following image shows the ASP.NET Web API Test Tool (running on http://xyz123.azurewebsites.net/) making a cross domain call to the Contoso domain. When you click Send, a cross-origin request is made. Because the Contoso site is not configured to support CORS, an error dialog is displayed.

clip_image002[4]

The CORS error appears on the Console tab of the IE F12 tools.

clip_image004[4]

For security reasons, the web browser doesn’t allow calls from the azurewebsites domain to the Contoso domain. With the new ASP.NET Web API CORS framework, Contoso.com can be configured to send the correct CORS headers so the browser will accept cross-origin calls.

clip_image005[4]

MVP Brock Allen contributed his CORS source to the ASP.NET Webstack repository. Brock worked with Yao Huang Lin (a developer on the ASP.NET team), to refine and iterate the design and then to get it pulled into the Webstack repository. Brock Allen, Dan Roth, and Yao discuss Brock’s CORS contribution in this Channel 9 video.

The CORS support for ASP.NET Web API page shows how to get started with this new feature.

Attribute-Based Routing in ASP.NET Web API

We recently published in the ASP.NET Web API roadmap our intention to support attribute- based routing in ASP.NET Web API. Route attributes bring the URL definition closer to the code that runs for that particular URL, making it easier to understand which URL must be called for a particular block of code and simplifying many common routing scenarios.

For example, let’s say you want to define a Web API that has the standard set of HTTP actions (GET, POST, PUT, DELETE, and so on) but you also want to have an additional custom action, such as Approve. Instead of adding another route to the global route table for the Approve action, you can instead just attribute the action directly:

    public class OrdersController : ApiController

    {

        public IEnumerable<Order> GetOrders() {…}

        public Order GetOrder(int id) {…}

        public Order Post(Order order) {…}

        [HttpPost("orders/{id}/approve")]

        public Order Approve(int id) {…}

    }

An extended route template syntax makes it simple to specify default values and constraints for route values. For example, you can now easily create two actions that are called based on parameter type. In the following People controller, the id parameter of the GetByID action takes only int values. The GetByName action method contains a default name of “Nick”.

    public class PeopleController : ApiController

    {

        [HttpGet("{name=Nick}")]

        public string GetByName(string name) {…}

 

        [HttpGet("{id:int}")]

        public string GetById(int id) {…}

    }

You can also define common route prefixes for your web APIs. For example, you can use route prefixes to set up a resource hierarchy:

    [RoutePrefix("movies")]

    [RoutePrefix("actors/{actorId}/movies")]

    [RoutePrefix("directors/{directorId}/movies")]

    public class MoviesController : ApiController

    {

        public IEnumerable<Movie> GetMovies() {…}

        public IEnumerable<Movie> GetMoviesByActor(int actorId) {…}

        public IEnumerable<Movie> GetMoviesByDirector(int directorId) {…}

    }

Or, you can use route prefixes to handle multiple versions of your web API:

    [RoutePrefix("api/v1/customers")]

    public class CustomersV1Controller : ApiController {…}

   

    [RoutePrefix("api/v2/customers")]

    public class CustomersV2Controller : ApiController {…}

Similar to the new CORS support in ASP.NET Web API, the new support for attribute-based routing is largely a contribution from the community. We are working closely with Tim McCall of attributerouting.net fame to bring many of the features of his AttributeRouting project directly into ASP.NET Web API.

It’s really exciting to see how these collaborations across the ASP.NET Team and the community are helping to move the ASP.NET platform forward!

Hope this helps,

Scott

P.S. In addition to blogging, I use Twitter to-do quick posts and share links. My Twitter handle is: @scottgu

20 Comments

  • Would it be possible to have this added to MVC as well?

  • Sweet, these look great and I'm glad Tim is being recognized for his hard work on AR. I'm glad I could contribute Web API support and he's taken it far; I know there were issues with certain things due to the Web API codebase but now that you guys are incorporating AR, hopefully we'll see first-party support!

  • I'm a big fan of Tim McCall's AttributeRouting package, and it's great news to have those features integrated with Web API!

  • I LOVE attribute routing!

    It should have been primary way to define routes from the MVC begginings.

  • I see that this is titled "Attribute-Based Routing in ASP.NET Web API". I am presuming (hoping Really Hard) that attribte based routing will be brought over to ASP.NET MVC as well. It would be Really Bad if that weren't the case.

  • This is great. Thanks Scott!

  • @Everyone - For now the team is focused on adding attribute routing to Web API, but we do have it in our plans to add it to MVC as well. We recognize that it's a super popular feature in both frameworks and we will try as hard as we can to make it available in both. But either way, Tim's original AttributeRouting will continue to be available for both, and will continue to work the same as it always did before.

    Thanks,
    Eilon (Dev Manager for MVC/WebAPI)

  • Attribute-base routing is really great for easily defining routes.
    There's only one stopping issue for me from using it in any of my signed web apps: it doesn't use the newly-signed WebActivatorEx 2.0.1.
    I hope it will be supported soon.

  • I love the attribute routing - definitely an increase in clarity. Quite a few times I've been looking around the view or the controller for a bug, only to find I've screwed up my routing. Having the route right there in the controller should help me not trip over myself as much!

  • Hi Scott,
    Does this supports .Net 4.0 (Visual studio 2010)?

    Thanks,
    Raju

  • This is excellent news. Tim McCall's AttributeRouting is a superb way to do your routing in a WebAPI project, I'm very glad to see it on the roadmap.

  • If the ASP.NET team doesn't put out a MVC version of the CORS library, then I will (that's based upon the new CORS bits mentioned here). In the meantime if you can't wait, then you can always use the open source CORS implementation from Thinktecture IdentityModel that was the basis for the contribution:

    http://brockallen.com/2012/06/28/cors-support-in-webapi-mvc-and-iis-with-thinktecture-identitymodel/

  • Hi Scott,

    Could you please tell how CORS support can be configured in web-api?

    Thank you very much.
    Kumanan.

  • Great additions! We also need Delta support for Patch operations (as with OData).

  • Can someone explain

    [RoutePrefix("movies")]
    [RoutePrefix("actors/{actorId}/movies")]
    [RoutePrefix("directors/{directorId}/movies")]
    public class MoviesController : ApiController
    {
    public IEnumerable GetMovies() {…}
    public IEnumerable GetMoviesByActor(int actorId) {…}
    public IEnumerable GetMoviesByDirector(int directorId) {…}
    }

    In further detail?

    What is going on with having multiple route prefixes applied to the singular controller?

  • I hope to see these in ASP.NET Web API soon. Great post!

  • pros and cons deploying asp.net mvc4 on windows 2012 iis 8 or windows 2008 server using iis 7

  • @Kumanan Could you please tell how CORS support can be configured in web-api?

    See Yao's blog http://blogs.msdn.com/b/yaohuang1/archive/2013/04/05/try-out-asp.net-web-api-cors-support-using-the-nightly-builds.aspx

    @Chris Marisic What is going on with having multiple route prefixes applied to the singular controller?

    The code shown was to define common route prefixes for your web APIs and route prefixes to set up a resource hierarchy. You probably want to use the following code:

    [RoutePrefix("api")]
    public class MoviesController : ApiController
    {
    [HttpGet("movies")]
    public IEnumerable GetMovies() { return null; }

    [HttpGet("actors/{actorId}/movies")]
    public IEnumerable GetMoviesByActor(int actorId) { return null; }

    [HttpGet("directors/{directorId}/movies")]
    public IEnumerable GetMoviesByDirector(int directorId) { return null; }
    }

    RoutePrefix just appends “api” to each route template decorated on the action here. So the final routes in the route collection would be like the following:

    “api/movies”, new{controller=”Movies”, action=”GetMovies”}
    “api/ actors/{actorId}/movies” , new{controller=”Movies”, action=”GetMoviesByActor”}
    “api/ directors/{directorId}/movies” , new{controller=”Movies”, action=”GetMoviesByDirector”}



  • attribute routing is awesome. but please...please fix the model binding for web-api. it's horrible to use [frombody] with it's limitations and [fromuri]. it comes across as poorly designed and I've seen others having pains with it as well.

  • I've worked on a project which uses attributes for routing and it doesn't feel right. First, it's clutters up the controller. Second, it's harder to manage and optimise your routes when they are littered among many controllers. Third, shouldn't the controllers just 'control' flow from the view rather than route as well?

Comments have been disabled for this content.