Admin Web Application

The eRegulations Admin WebApp allows a user with the correct credentials to enter the back office space of the system and to update the eRegulations content.

The management of information is built on three main pillars that target the main areas of the application:

  1. eRegulation Content
    Here below the principal repositories:
    • procedures, blocks of steps, steps and recourses
    • contacts (entities, units and persons in charge)
    • requirements
    • laws
    • media library
  2. Public Interface (public web pages)
    The admin application is also responsible for the information displayed on the public web site of e-regulations. We identified the following editable elements:
    • layout home page
    • the procedure menus that assures not only direct linking with the procedures in the eRegulations content but supplementary visual information to be displayed in the public pages
    • about us page
  3. Country parameters (system utility-belt)
    In this are the system groups several utility modules that helps the administrator manage auxiliary information present within the system:
    • user management
    • feedbacks listing
    • country settings (cost variables catalogue, foreign currencies used in the public system, third parties catalogue)
    • label translation for the admin/public web pages
    • history tracking of eRegulations content modifications
    • files maintenance (possibility of file name changing into more web friendly names for uploaded documents or images)

1. Application architecture

The architecture of the Admin Web Application follows a 3-tiers design : Data, Business, Presentation.

We implemented the Interface Segregation Principle for decoupling the Data Access Layer implementation from the contract definition allowing in the future for easy update in case of more powerful technologies. Also the Data Access Layer was designed to implement the Repository pattern and Unit of Work pattern to assure the transactional action of persisting the data.

Also for the web application we implemented the Model View Presenter pattern and define the views as interfaces gaining in flexibility of implementing the view interfaces as ASPX pages or as customized views for Ajax requests.

The domain modeling respects the Domain Design Driven principles by defining several Root Aggregate Model responsible for the persistence of all their collections of composite models.

We illustrate in the following diagram the layered architecture of the solution :

2. Data-concepts and states

The system is built around the following main concepts:

  • Objective – a concrete investment operation presented as a ordered list of blocks
  • BlockOfSteps – a ordered list of steps with a high level of cohesion
  • Step – any interaction necessary to achieve the objective

The Objectives are organized in a tree-way, in the sense that first there can be defined a list of main objectives, further permitting a detailed filtration of them in sub-objectives.

A Block of steps can be qualified as optional therefore all the contained steps will be treated as optional within the objective. Also a block is responsible for setting the order of steps and also the relation of each step with the previous one (either parallel, alternative or sequential)

A Step is described with several categories of info:

  • general info
  • results of steps
  • contact
  • requirements
  • costs
  • timeframe
  • legal frame
  • additional info
  • recourse

The system is also the manager of several repositories that are highly linked to the description of one step. They are self-manageable repositories

  • Entities in charge
  • Units in charge
  • Persons in charge
  • General requirements ( downloadable forms, sample forms, online form links, documents, etc)
  • Laws (articles, full laws - either web links for online bookmarking or uploaded documents)
  • Media library (all the documents uploaded are stored in media library in logical objects that decouples the media file from the database reference for easy maintenance)

All the eRegulations content follows the principle of internationalization by providing the data in one principal language, usually the country official language and in a secondary language, usually an international language.

All the data-entry form will assure the persistence of data in the principal language leaving to special graphical interfaces for translation of content. There is also a special "external admin interface" called the Translator Admin WebApp that will allow an authorized translator to enter a specialized backoffice and update/request for publication of translation of content.

Managing the State of a Data

Procedure, BlockOfSteps and Step are stateful objects in the sense that at any time any of it can have only one state.

The possible states are:

  • MODIFIED
  • PUBLISHED

The following diagram describe the lifecycle of a Step, and the actions which will change its present state :

When published the data is stored in a different format that is less normalized, still highly optimized for data-consumption systems.

The system is capable of storing a complete snapshot of a procedure at a specified moment in time. A procedure can have several snapshots that will allow us to reconstruct the full version of that procedure at that particular time. When taking this snapshot the system crawls through the full graph of domain model in order to retrieve the information for root objects as well as for all the dependencies.

The snapshots are persisted in special tables in the database, tables that are prefixed with "snapshot_".

The snapshots tables have been designed for fast retrieval and query operations and are a less-normalized replica of the eRegulations content. A special record of the snapshots data is the current snapshot which responds to the need of frequent publish actions of the current eRegulations data.

Each time we publish a stateful object the correspondent snapshot data is reconstructed.


3. Domain model

Step context diagram

The diagram below will illustrate as example the domain modeling of the Step as the Root Aggregate Class and all the collection of bound classes. StepContextDiagram

The entire model of the eRegulations system has been implemented following a Domain Driven Design approach.

eRegulations data structure

The structure of the data is here.


4. Code execution flow

We will illustrate in this section the code execution flow for two possible cases of user interaction with the admin web application.

  • requesting a new page
  • triggering an action on the page (update information, publish, change the order of elements, etc)

Requesting a new page

Page Get Sequence Diagram

Requesting a new page will involve the creation of a new instance of System.Web.UI.Page. Depending on the page requested the Asp.Net Page must implement the correspondent IView interface.

We will exemplify for viewing the details page of one step:
1. User makes a request in the browser by clicking on a hyperlink. The request will send as a query parameter the ID of the requested step.

Here the sequence of code:

  1. IIS identifies the requested resource as "StepGeneral.aspx" inside the admin application, so it forwards the request to our application
  2. Asp.Net creates a new instance of the object "Views_Regulation_StepGeneral"
  3. Asp.Net trigger the event "Page_Load"
  4. Inside the "Page_Load" we create a new instance of the presenter sending in the constructor the current instance of Views_Regulation_StepGeneral as this class implements the interface IStepView and the AppContext which is an application context that travels through all the layers. The AppContext is created each time a request is intercepted by our application. It is cached through the duration of the request in the HttpContext
  5. the newly created presenter will call the method InitView send the stepId as parameter
  6. the presenter holds all the presentation logic. It has a reference of the "IView" interface which will use for displaying the information. Still is not aware of how this interface is implemented (in our case is the System.Web.UI.Page)
  7. the presenter will create a new instance of the BusinessObjectAPI related to our need (in our case StepBO)
  8. the BusinessObjectAPI holds a reference to the Root Aggregate Class (in our case Step). the presenter creates a new instance of the model, it sets the Id of the model and it attaches it to the BusinessObjectAPI.
  9. the presenter demand the BusinessObjectAPI to load the model
  10. the BusinessObjectAPI will call the RepositoryFactory in order to retrieve an instance of IRepository that will use for talking to the DataLayer (it will return an instance of LiqRepository)
  11. the BusinessObjectAPI uses the IRepository instance and load the model from the data (the repository will call a SQL query that will be executed against the SQL Server DB and the load the model with the db data)
  12. the BusinessObjectAPI holds a collection of errors in case any operation performed raised an error
  13. the presenter verifies if the load of model was ended successfully and if so it tells the IView (in our case the Regulation) to display the details of the model . If the process of loading the data failed, the presenter calls the "ShowErrors" method of the IView to display the errors
  14. inside the System.Web.UI.Page methods/properties of the IView implementation we set the data to html elements
  15. the System.Web.UI.Page finishes the cycle and display the html output


Trigger an action on the page (update)

Page Post Sequence Diagram

Sending a post request to the server is 99% made through an Ajax call (with a XMLHttpRequest). The end point is a static method in the aspx page having the attribute [WebMethod].

Inside this static method we create an instance of the custom view that implements our IView interface (IStepView). We will use the same presenter (StepPresenter) together with our custom view in order to achieve our updating purpose. The difference is the transport of all the data that the browser will exchange with the server. In the case of the Ajax call we encapsulate the data in Data Transfer Objects (DTO) which are light objects holding only property fields. In the case of classic Http post request the transport would have been the form input collection send either encoded in the url as query string or send as payload inside the body of the http request message.

All the custom views are extended from a base class called BaseWebView that holds all utilities needed by all the custom views.

The AppContext is also created each time a request is handled. It is also cached in the current HtppContext managed by the Asp.Net framework.

We will exemplify for updating the details page of one step: 1. User clicks on the "SAVE" button inside the step page. The client side code will wrap all the data from the editable fields in a JSON object and the sends a new XMLHttpRequest to the endpoind " StepGeneral.aspx/Update" with the payload the newly JSON object that will deserialize into a DTO C# Object and a ID parameter with the value equal to the StepID.

Here the sequence of code:

  1. IIS identifies the requested resource as "StepGeneral.aspx/Update" inside the admin application, so it forwards the request to our application
  2. Asp.Net searches for the static method "Update" having the [WebMethod] attribute inside the class behind the "StepGeneral.aspx" page and calls this method
  3. we retrieve the AppContext
  4. create a new instance of our custom view that implements the interface IStepView (in our case UpdateView). Send in the constructor the DTO received
  5. create a new instance of the presenter sending the instance of our custom view and the AppContext
  6. the newly created presenter will call the method Update send the stepId as parameter
  7. the presenter holds all the presentation logic. It has a reference of the "IView" interface which will use for retrieval of all the necessary information to update the model. Still is not aware of how this interface is implemented (in our case is the instance of CustomView)
  8. the presenter will create a new instance of the BusinessObjectAPI related to our need (in our case StepBO)
  9. the BusinessObjectAPI holds a reference to the Root Aggregate Class (in our case Step). the presenter creates a new instance of the model, it sets the Id of the model and it attaches it to the BusinessObjectAPI.
  10. the presenter demand the BusinessObjectAPI to load the model
  11. the BusinessObjectAPI will call the RepositoryFactory in order to retrieve an instance of IRepository that will use for talking to the DataLayer (it will return an instance of LiqRepository)
  12. the BusinessObjectAPI uses the IRepository instance and load the model from the data (the repository will call a SQL query that will be executed against the SQL Server DB and the load the model with the db data)
  13. if no errors encountered the presenter will ask the view to update the model. As our custom view received through the constructor the DTO sent by the user it will use it to update the model.
  14. then the presenter will ask the IRepository instance to persist the modifications
  15. the BusinessObjectAPI holds a collection of errors in case any operation performed raised an error
  16. the presenter verifies if the update of model was ended successfully and if so it raises an event called SavedSuccessfully. (normally in the custom view you will write an SavedSuccessfullyHandler where you will have a flag holding the operation response. If the process of loading the data failed, the presenter calls the "ShowErrors" method of the IView to display the errors (the custom view will hold the errors inside a collection of errors)
  17. the webMethod then verifies if the success flag of the custom view is true and sends a ok message to the browser. If custom view has errors inside its collection, the webMethod will throw an ApplicationException with the message holding the serialized version of all the view errors.

5. Procedure snapshots

As already mention the system allows you to register a full snapshot replica of one procedure. The snapshot is saved in specialized tables that are less normalized and holds the data in both the principal and secondary languages.

Each time a user clicks on "Save snapshot" button in the admin interface the system makes a deep copy of the data for one procedure.

The data saved for one procedure is:

  • objective full data
  • blocks of steps full data
  • steps full data (and for each element used form the Repositories it copies the current full data: full data for GenericRequirement, Law, EntityInCharge, UnitInCharge, PersonInCharge)

The last undated snapshot, called also the "current snapshot" is used for keeping the current published data of eRegulations procedures content.

Also the eRegulations Data API Publisher retrieves the information for one procedure from the current snapshot and send it to the eRegulations Data API Server.

The reconstruction of the current snapshot of one procedure is triggered by each of the following events:

  • publish an objective
  • publish a block
  • publish a step
  • publish a recourse
  • update an item in GenericRequirement repository for all the procedures where that GenericRequirement is used
  • update an item in Law repository repository for all the procedures where that Law is used
  • update an item in EntityInCharge repository repository for all the procedures where that EntityInCharge is used
  • update an item in UnitInCharge repository repository for all the procedures where that UnitInCharge is used
  • update an item in PersonInCharge repository repository for all the procedures where that PersonInCharge is used
Note: The tables do not have a strong link between them, there are no foreign keys that enforce the restriction for the data, as the data is automatically generated through the execution of special stored procedures easily identied as they all holder the "snapshot" word in their names:
  • sp_snapshot_get…
  • sp_take_snapshot…

The table of the structure of the snapshots is here.


6. History tracking of eRegulations content modifications

The eRegulations domain model is fully aware of "dirty" properties and right before updating the model into the database it iterates through all the models registered in the DataContext (RootAggregate object and all the aggregate/composite objects) and stores the modifications of those updated properties.

A "dirty property" of an object is that property that changed its original value, the original value being the one retrieved from the database.

As described earlier in the document the process of updating a model in the database implies the first loading of the current data from the database , update only a precise list of properties from that model (depending in which context you are) and then ending by persisting the modifications in the database.

The implementation of IRepository is capable of having this low-level verification the moment before throwing all the updates in the database. It is based on the DataContext that assures the Unit of Work action of persisting the data.

We will list here the structure of the audit tables that hold the original and modified value of each field of the model. It also takes account the root aggregate object and the relations of dependent objects to that root aggregate object.


7. Label translation

The eRegulation Admin Interface & Public Interface static texts are fully managed by the eRegulations system . All the titles, all the messages, all the labels are updatable through the "Country parameters -> System translation" page.

The texts are stored in sequential files organized in a tabular manner:

labelId | labelTranslationInLang1 | labelTranslationInLang1 | ...

The texts are organized in several files following a logical separation of contextual ussage. The totality of files gives as the translation dictionary used by the system.

One system works with two dictionnaries: Local and Central. A central dictionary can be used by several admin systems installed on the same server. When looking up a certain label the system will look first if the translationModule (file) exists in the local dictionary and if the module contains a local translation of that label. If found the system will return that translation. If the translation is not found in the local dictionary the system will look it up in the central repository and it will return the translation found.

The call for the translation of a label is:

GetMultilangValue("labelKey", "default translation text", "translationModule")

Feedback