title: How to Route non-CRUD actions in a RESTful ASP.NET Web API?
body: <p>I am trying to design a RESTful web API for our service using ASP.NET Web API.  I'm running into trouble with figuring out how to route non-CRUD actions to the proper controller action.  Let's assume my resource is a door.  I can do all of the familiar CRUD things with my door.  Let's say that model for my door is:</p>
  
  <pre><code>public class Door
  {
     public long Id { get; set; }
     public string InsideRoomName { get; set; }
     public string OutsideRoomName { get; set; }
  }
  </code></pre>
  
  <p>I can do all of my standard CRUD operations via my web api:</p>
  
  <pre><code>POST: http://api.contoso.com/v1/doors
  GET: http://api.contoso.com/v1/doors
  GET: http://api.contoso.com/v1/doors/1234
  GET: http://api.contoso.com/v1/doors?InsideRoomName=Cafeteria
  PUT: http://api.contoso.com/v1/doors/1234
  DELETE: http://api.contoso.com/v1/doors/1234
  </code></pre>
  
  <p>and so on.  Where I run into trouble is when I need to model the non-CRUD actions against my door.  I want to model a Lock and Unlock verb against my resource.  Reading through the <a href="http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api" rel="noreferrer">ASP.NET articles</a> the guidance seems to be to switch to an RPC style call when using custom actions.  This gives me a path:</p>
  
  <pre><code>PUT: http://api.contoso.com/v1/doors/1234/lock
  PUT: http://api.contoso.com/v1/doors/1234/unlock
  </code></pre>
  
  <p>This seems to conflict with the spirit of REST which aims for the path to indicate a resource.  I suppose I could model the verb as a resource:</p>
  
  <pre><code>POST: http://api.contoso.com/v1/doors/1234/lockrequests
  POST: http://api.contoso.com/v1/doors/1234/unlockrequests
  </code></pre>
  
  <p>In this case I could still use the recommend {controller}/{id}/{action} but it seems like I'm still creating a mixed RPC / REST API.  Is it possible, or even recommended as far as REST interfaces go, to put the custom action in the list of parameters?</p>
  
  <pre><code>PUT: http://api.contoso.com/v1/doors/1234?lock
  PUT: http://api.contoso.com/v1/doors/1234?unlock
  </code></pre>
  
  <p><strong>I could foresee a need to have this call supported with query parameters as well, such as:</strong></p>
  
  <pre><code>PUT: http://api.contoso.com/v1/doors?lock&amp;InsideRoomName=Cafeteria
  </code></pre>
  
  <p><strong>How would I create the route to map this request to my DoorsController?</strong></p>
  
  <pre><code>public class DoorsController : ApiController
  {
     public IEnumerable&lt;Doord&gt; Get();
     public Door Get(long id);
     public void Put(long id, Door door);
     public void Post(Door door);
     public void Delete(long id);
  
     public void Lock(long id);
     public void Unlock(long id);
     public void Lock(string InsideRoomName);
  }
  </code></pre>
  
  <p>I may be making some false assumptions here regarding what is and is not best practices with respect to REST API design, so any guidance there is appreciated as well.</p>