WebAPI REST Routing For AngularJS and ExtJS

As most of my readers know, I’ve done a lot of work with the JavaScript libraries made by Sencha (ExtJS and SenchaTouch).  The typical JSON sent down to the requesting web application looks like the following with both Sencha products.

{
  "data": [
    {
      "shirtSize": "Mens-4XL",
      "id": 30
    },
    {
      "shirtSize": "Mens-5XL",
      "id": 31
    },
    {
      "shirtSize": "Mens-6XL",
      "id": 32
    }
  ],
  "total": 34,
  "success": true
} 

Notice that it is a single JavaScript object that has a property named data which is the array we are interested in.

AngularJS’s Resource api expects just the data array by default without the nice wrapping with total and status.  That is, Angular just wants this:

[
    {
      "shirtSize": "Womens-L",
      "id": 4
    },
    {
      "shirtSize": "Womens-XL",
      "id": 5
    },
    {
      "shirtSize": "Womens-2XL",
      "id": 6
    },
    {
      "shirtSize": "Mens-S",
      "id": 7
    }
  ]

The default routing in Microsoft’s ASP.NET WebAPI 2 is such that a rest controller always formats data the same and it is non trivial to write a special filter to convert the results to one format or the other based on something like a request header.  The work around I came up with to allow basically one WebAPI service to handle both types of output was to have the REST call be slightly different.  The original REST calls to get data were as follows:

…/rest/ShirtSize and …/rest/ShirtSize/31

That is, the two above URLs always get me the full result including the total and success value.  What I want is another REST call I can use in AngularJS that will return me just the array.  My design calls for the following two URLs to do that.

../rest/ShirtSize/ArrayOnly and /rest/ShirtSize/ArrayOnly/31

To do this in WebAPI is quite simple.  All we need to do is add to our routing file (WebApiConfig.cs) the following code.

config.Routes.MapHttpRoute
    ("API Presenter ArrayOnly", "rest/presenter/arrayonly/{id}",
        new
        {
            controller = "presenter",
            arrayonly = 1,
            id = RouteParameter.Optional
        });

Then, in our WebAPI controller itself we have the following method signature.

 
public HttpResponseMessage Get(int? arrayonly=null,int? id = null)

Now, when the WebAPI call happens without arrayonly specified we get the default behavior which includes the success and count but when arrayonly is passed in the parameter line we can return a custom response that just has our array.

HTH’s!

About Peter Kellner

Peter is a software professional specializing in mobile and web technologies. He has also been a Microsoft MVP for the past 7 years. To read more about Peter Kellner and his experience click here. For information about how Peter Kellner might be able to help you with your project click here.

Follow me:


Comments

  1. Peter Kellner says:

    Thanks Jon, I’ll start using that instead of limiting what I download. I’m planning on learning ngGrid which I think supports paging and I’m sure I’ll need the extra info.

  2. You can use transformResponse or an interceptor to modify the $resource. Very handy but limited documentation. See this StackOverflow post for an example http://stackoverflow.com/questions/21927819/angularjs-transform-response-in-resource-using-a-custom-service

  3. Peter Kellner says:

    Jon, How would you strip out the extra data with $resource? that’s what caused me to go down this path.

  4. This seems very messy to me.
    Angular can accept data in any format and those extra pieces of information such as the total could be useful for your client.

    If you’re not bothered about them however why not simply return the list of Shirt Sizes

    public IEnumerable Get(int? id = null)

Follow

Get every new post delivered to your Inbox

Join other followers: