AngularJS–Part 5, pushing data to the server

Introduction

This is a series of posts to describe our approach to slowly migrate a Silverlight based client of a huge and complex LOB  to an HTML5/CSS3/JavaScript based client. These posts report on the lessons learnt and are meant to be used as a reference for our development teams. The first few post can be found here

In my last post I introduced the $http service that can be used to access server side resources. So far we have looked at how we can query data on the server by using the HTTP GET method. In many web applications the HTTP GET method is used a lot more often than any other method. But from time to time we want to push some data gathered from the user to the server. Here we have various methods to do so. the most common methods are the HTTP POST, PUT or DELETE methods.

In this post I will also for the first time discuss some specifics of the architecture of our enterprise application and what that means for the design of our Web client. But lets first start with the basics.

Sample

We will create a simple sample to demonstrate the use of the $http service to send data to the server. In this sample we will use pretty much all the techniques that we have learned so far. In our sample we want to display a list of existing tasks with their status. We also want a Refresh button which we can click to get the latest list of tasks if we think that our currently displayed task list is stale. The list of tasks shall be provided by a RESTful service.

Let’s open our HelloAngular sample in Visual Studio. Add another HTML page called step5.html to the solution. Also add a JavaScript file step5.js to the solution. In the JavaScript file define an AngularJS application called MyApp. Add a controller TaskListCtrl to the AngularJS application. In the controller constructor use the $http service to access the list of defined tasks at the URI api/tasks. When the call successfully return assign the data of the response to the variable tasks defined on the $scope. So far our JavaScript file should look like this

image

The HTML snippet to display the list of tasks looks like this

image

It is simply an unordered list with a list item for each task in the tasks collection of the controller. The above HTML snippet is nested in a div tag which has the ng-controller directive as an attribute. Just as a reminder: the whole part of the view which is nested inside a tag with a ng-controller directive is managed by the respective controller. Below the list of tasks we also want a button which when clicked will reload the tasks from the server in case our data has become stale. The button click event is linked to a refresh() method of the controller via the ng-click directive. All in all the complete view area managed by our TaskListCtrl controller looks like this

image

Now we need to define the refresh function on the $scope of the controller. Thus our controller looks like this

image

The body of the function is just a copy of the $http.get call that we had already implemented earlier. We can now run the application (assuming we have a RESTful service listening at api/tasks and providing us a JSON-formatted list of tasks)

It is of course bad to have such a code duplication and we should refactor the controller. This is what we get

image

Sample REST service

When using Visual Studio 2012/2013 we can simply add a Web API controller to our project. In this controller we only need to implement the Get method so far. In our simple sample the Get method shall return a pre-canned list of sample tasks.

image

where the class Task is defined like this

image

and the TaskStatus enumeration like this

image

We need to bootstrap the REST service thus we add a Global.asax file to the project and define the code behind as follows

image

In the GlobalConfiguration class we just define the server routing such as that the URI api/tasks that we use in our AngularJS client maps to the Get method of the TasksController class.

image

Creating a new task

In our view lets define a new region where we can create a new task by entering a task name and pushing this new task to the server when clicking a create button. This area shall be managed by its own controller NewTaskCtrl and the controller shall be a child of the TaskListCtrl. Thus we nest the area inside the div that contains the ng-controller directive for the TaskListCtrl controller.

image

When looking at the above snippet we can see that we need to define a new Angular controller having a taskName property and a createTask function defined on the $scope.

image

In the body of the createTask function we have to put the logic which takes the task name entered by the user and pushes this value to the server. We will use the $http.post method to send our task to the backend. If everything goes well the server responds with a location entry in the response header. This location entry will contain the URI to the newly created task. We will then use $http.get with this URI to retrieve the new task and once we get it from the server append it to our tasks collection. Since the tasks collection is defined on the $scope of the TaskListCtrl controller and we are in the NewTaskCtrl controller we only have access to this collection if the NewTaskCtrl is a child controller of the TaskListCtrl.

image

The post method accepts the URI as a first and the payload (content) as a second parameter. The post method is again an asynchronous method and thus returns a promise. We can register a success function  (and optionally also an error function) with the promise. As detailed in the documentation the success callback function has the three parameters data, status and headers where data represents the content of the response, status represents the status code returned by the server in the response and headers is a collection of name value pairs as found in the header of the server response. From the headers collection we extract the location value which we use in the subsequent $http.get method call.

Lets look at the server side and extend our REST service. We add a Post method to the TasksController which will just create a new Task instance with the data received from the client and append this task to the list of per-canned tasks. The response to the client is then enriched with a location header entry which will contain the URI to the newly created task, e.g. app/tasks/7 if the new tasks has ID=7.

image

We also need to provide a method in our REST service to handle Get requests for a single task. This is simple

image

And now we are ready to run our application and create some new tasks.

Can we improve?

Not only should we push the data to the server but also we should tell the server the context, that is, we send a command to it.

If we provide context to the server, then the server knows what to do with the data. This kind of operation is very different from a classical CRUD approach where the client just tells the server to CREATE/INSERT or UPDATE something. Insert and update (or even more general SAVE) methods are very generic and they do not reveal the intent of the client. The “why does the client want me to do something?” question goes lost when only using generic save operations.

CQRS and REST

There is a lot of discussion about whether the two concepts of REST and CQRS can be combined in a meaningful application. As we will see the answer is yes, of course. Others have written some profound articles about combining REST with CQRS. Thus I invite you dear reader to read those articles if you want to dig a little bit deeper. I specifically want to point out this article which was just published a couple of days ago on InfoQ.

I can see 3 ways of combining a RESTful API with CQRS

  • Send the command as payload to a URI containing the command type, e.g.
    URI: api/tasks/1/complete
  • The request body contains the command type as well as the command itself, e.g.
    URI: api/tasks
    Body: { CommandType: “CompleteTask”, Command: {} } or
          { CommandType: “ChangeDueDate”,
            Command: { DueDate: “1/1/2014” } }
  • The request header contains the command type and the body contains the command
    URI: api/tasks
    Header: Command-Type: “ChangeDueDate”
    Body: { DueDate: “1/1/2014” }

Personally I favor the last variant and will use it in our sample.

That said, lets adjust out code. To define a custom header in our POST request we can use the optional config parameter and within define our custom header CommandType. We want to create a new task and thus we change our createTask function as follows.

image

Note that the config parameter is optional and it is the third parameter of the post method. On the server side we have to unwrap the custom header and can the use it to determine what the context of the POST request is. In our sample we will reject any command type other than CreateTask.

image

In a more complex situation with many possible command types we would probably use the strategy pattern to handle the individual commands.

Using the developer tools of the browser we can see that the header of our POST request indeed contains the custom entry CommandType and the header of the response contains the Location header with the URI pointing to the newly created task.

image


Summary

I have discussed how we can transfer data entered by a user to the server by using the $http service. Since our enterprise solution is not the typical CRUD type application we use CQRS as an architectural pattern. Our client sends intention revealing commands to the backend instead of just very generic “save” requests. I have shown how we can create such a command in AngularJS and send it to the server. Finally I have also shown how a simple implementation of a RESTful service backing our Angular client can look like.

I have added the code that I presented so far in my series about AngularJS to GitHub. It can be found here.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 12 years as an independent consultant, trainer, and mentor mainly on the .NET platform. He is currently working as chief software architect in a mid-size US company based in Austin TX providing software and services to the pharmaceutical industry as well as to many well-known hospitals and universities throughout the US and in many other countries around the world. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in AngularJS, CQRS, introduction, REST. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Scott MacLellan

    I was wondering why you picked the last option for how to send the data back. The uri based is definitely my favourite since you can easily split up the logic within your controller and have used the second in the past reasonably well. Thanks for this excellent series and I am looking forward to more.

    • gabrielschenker

      I still pretend to have a RESTful API on the server and REST URIs cannot contain verbs. But commands are verbs (or contain verbs, e.g. Create, publish, cancel, etc.). This eliminates the first approach. If on the other hand you do not care about complying REST requirements then it is a perfectly valid option

    • Alper

      From the referenced article:
      One common approach is using RPC-style resources for example /api/InventoryItem/{id}/rename.
      While this seemingly removes the need for arbitrary verbs, it is
      against REST’s resource-oriented presentation. We need to be reminded
      that a resource is a noun and HTTP verb is the verb/action and self-descriptive messages (one of the tenets of REST) are the vehicle to convey other axes of information and intent

      • gabrielschenker

        I am not religious about this but other people that are more skilled than I am in designing REST APIs have give some good reasons why verbs are bad in URIs. Just search for e.g. “restful api uri verbs” and you will find quite a few good articles.

  • Alper

    I like the uri based option as well. Once you define the custom routes to handle /api/Tasks/1/, it looks like you can get rid of the code that deals with the header both on the client and on the server. Self-documenting uris are useful too. Do you know why REST URIs cannot contain verbs?

  • lennybacon

    Hi Gabriel,

    I think there is a 4th way that I would prefer over the 3 you mentioned.

    The RFC 2616 says “HTTP allows an open-ended set of methods and headers that indicate the purpose of a request”

    and

    “The set of common methods for HTTP/1.1 is defined below. Although this set can be expanded”

    So in the example what you call command (e.g. “ChangeDueDate”) would be the method.

    The client can figure out what methods are available by requesting the standard methods OPTIONS and ALLOW.

    IMHO this is closer to the specification of HTTP as application protocol.

    Best Regards,

    Daniel

  • Vlad Kopachinsky

    About CQRS and REST

    Our company use CQRS and found solution ( code name as MVD ) .
    MVD ( model view dispatcher ) is a design pattern to execute a Command / Query without writing an Action ( in Controller ).

    You can read about this in article ( http://blog.incframework.com/en/model-view-dispatcher/ ). MVD one part of open source project Incoding Framework ( https://github.com/IncodingSoftware/Incoding-Framework )

  • Deyan Petrov

    What about the following variation of option 2:

    URI: api/tasks/1/actions (or commands, but actions sounds nicer in the API)
    Body: { ActionType: “ChangeDueDate”, DueDate: “1/1/2014” } (very flat, access ActionType field for getting the handler)

    Option 3 sounds a bit strange to me as:

    1) You are posting to /tasks, instead of referring to tasks/1
    2) You are sending a single field, not the whole resource representation – shouldn’t that be actually a patch?

    • gabrielschenker

      Our solution is not a CRUD style application and we use CQRS. Thus we basically have queries (HTTP verb GET) and commands (HTTP verb POST). We selected POST since it is the most generic/unrestricted of all standard verbs that allow for modification of resources. But that is just our personal preference and I’m sure other approaches are perfectly valid too.

      • Deyan

        I am also speaking in terms of a CQRS service (non-CRUD).
        My questions is why POST to /tasks a command – doesn’t this sound strange, as usually you POST to /tasks a new task … Wouldn’t it be nicer to POST to /tasks/1/actions, especially in the case when aggregates are often event-sourced state machines, where each state allows certain actions …