10

As a result of a previous question of mine, I have discovered two ways of handling REST routes in MVC3.

This is a followup question where I am trying to learn factual differences/subtleties between these two approaches. I am looking authoritative answer if possible.

Method 1: Single Route, with Action Name + Http Verb Attributes on Controller Actions

  1. Register a single route in Global.asax using a specified action parameter.

    public override void RegisterArea(AreaRegistrationContext context)
    {
        // actions should handle: GET, POST, PUT, DELETE
        context.MapRoute("Api-SinglePost", "api/posts/{id}", 
            new { controller = "Posts", action = "SinglePost" });
    }
    
  2. Apply both ActionName and HttpVerb attributes to controller actions

    [HttpGet]
    [ActionName("SinglePost")]
    public JsonResult Get(string id)
    {
        return Json(_service.Get(id));
    }
    [HttpDelete]
    [ActionName("SinglePost")]
    public JsonResult Delete(string id)
    {
        return Json(_service.Delete(id));
    }
    [HttpPost]
    [ActionName("SinglePost")]
    public JsonResult Create(Post post)
    {
        return Json(_service.Save(post));
    }
    [HttpPut]
    [ActionName("SinglePost")]
    public JsonResult Update(Post post)
    {
        return Json(_service.Update(post););
    }
    

Method 2: Unique Routes + Verb Constraints, with Http Verb Attribute on Controller Actions

  1. Register unique routes in Global.asax with HttpMethodContraint

    var postsUrl = "api/posts";
    
    routes.MapRoute("posts-get", postsUrl + "/{id}", 
        new { controller = "Posts", action = "Get",
        new { httpMethod = new HttpMethodConstraint("GET") });
    
    routes.MapRoute("posts-create", postsUrl, 
        new { controller = "Posts", action = "Create",
        new { httpMethod = new HttpMethodConstraint("POST") });
    
    routes.MapRoute("posts-update", postsUrl, 
        new { controller = "Posts", action = "Update",
        new { httpMethod = new HttpMethodConstraint("PUT") });
    
    routes.MapRoute("posts-delete", postsUrl + "/{id}", 
        new { controller = "Posts", action = "Delete",
        new { httpMethod = new HttpMethodConstraint("DELETE") });
    
  2. Use only an Http Verb Attribute on the Controller Actions

    [HttpGet]
    public JsonResult Get(string id)
    {
        return Json(_service.Get(id));
    }
    [HttpDelete]
    public JsonResult Delete(string id)
    {
        return Json(_service.Delete(id));
    }
    [HttpPost]
    public JsonResult Create(Post post)
    {
        return Json(_service.Save(post));
    }
    [HttpPut]
    public JsonResult Update(Post post)
    {
        return Json(_service.Update(post););
    }
    

Both of these methods let me have uniquely named Controller Action Methods, and allow for RESTful routes tied to the verbs... but what is inherently different about restricting the route vs. using a proxy action name?

Community
  • 1
  • 1
one.beat.consumer
  • 9,414
  • 11
  • 55
  • 98

3 Answers3

1

You won't get an authoritative answer by here are my 2 cents:

I prefer method 2 because then you have all your routing in one place. You can encapsulate your routing into a method e.g. MapResourceRoutes(string controller, string uri) and have it used muptiple times throughout your API.

Also method 2 gives you clearly named routes that you can use for linking and reverse routing.

Kugel
  • 19,354
  • 16
  • 71
  • 103
0

At this point, the correct answer is use Web API.

one.beat.consumer
  • 9,414
  • 11
  • 55
  • 98
0

I don't know that you will ever find an authoritative answer, but I will offer my opinion and as you can tell by my points, my opinion matters ;-). My purist self thinks that the first option is more pure, however my experience has been that helper methods like Url.Action() can sometimes have trouble resolving the correct route with this approach and I have taken to the second method as it really only has implications internally as the api looks identical to the consumer.

Jimmy Bosse
  • 1,344
  • 1
  • 12
  • 24