Allowing a user to undo actions they have taken is basic functionality in most computer applications.  Recently, I was working on a custom LOB application for a client that would allow them to interact with an offline repository of their data. They needed the ability to undo actions that affected several Sqlite tables at once. There was a further requirement that the end user be able to walk back all changes made since the last synchronization to the master database (accessed via a WebAPI service). I therefore needed to come up with a mechanism to store each action that a user had taken, along with all the changes that were made in the database.

In this post, I will build on the basic structure I built in a previous blog post, where I created a very basic Contact management app. I will add functionality to “undo” changes as they are made. Changes are tied to the controller, so that selecting Undo on the Contacts controller will not roll back changes made in a different controller.


  1. Update the Database configuration to store data in “auditTransaction” and ”auditAction” tables.

  2. Add models for Audit Action and Audit Transaction

  3. Add the Audit Service. This service will handle creating transactions, linking transactions to actions taken, and actually performing Table CRUD operations. In addition, the rollback/undo functionality will be handled in this service.

  4. Add to the Contacts controller:
    • Load the $scope.AuditLog array with transactions eligible to be rolled back.
    • Wrap calls to the database in calls to the Audit Service.
    • Add calls for undo.


  5. Add undo button to the Contacts Template.


  6. Run the app, and click the Contacts tab.Add contacts to the list and verify that you can remove them via the undo functionality.
  7.  contacts-undo-available  contacts-undo-confirm  contacts-undo-done


While this example is relatively simple, you can chain numerous steps into a single transaction, allowing complex functionality to be reversed via a single action.

Like this post? Share it!