Author Archives: bcblog

Developing HTML for Power Users

Who is a power user?
Power users can be users who are using a website beyond the capabilities the website was originally designed. When an internal website is designed correctly, a power user would be a good candidate for initial training. They are also generally used as first-level in-house support. The other type is a user who is trying to break into the website. While not all power users are hackers, all good hackers are power users. For proper design, a website must be able to accommodate the power user while not allowing them to hack into the website.

Multiple Open Windows
A power user will often open a webpage in multiple windows to review one set of data while updating another screen. On the older versions of IE, this was as easy as pressing ctrl+n, and getting a new window within the same session. On the newer browsers, opening another instance of the same browser in any way will open the browser within the same session.

Some multiple window issues will be solved in the same way the website deals with multiple users. The difference between multiple users and multiple windows is multiple windows will share the same user information as well as the same data on the server (session information). Without using advanced techniques, it is not possible to tell which window is submitting the information.

Scenario: A user is shopping on a website and places items in the shopping cart. While reviewing the shopping cart, they realize they are missing an item, so they open a second window, perform the search and add the item to the shopping cart. After adding the new item, they close the second window, returning to the shopping cart window. By default their new item is not shown in the shopping cart on the screen, but the item is in the shopping cart on the server. If the user refreshes the screen, the item will generally appear correctly in the shopping cart. The problem occurs if the user proceeds to the checkout without refreshing the screen. For this example the user is allowed to modify quantities in the shopping cart before proceeding to the checkout. If the server does not check to see if the shopping cart has been updated since the client side shopping cart was last refreshed, the quantity of the new item would come across as a blank, which would either be considered a data entry error, or be interpreted as 0, thereby removing it from the shopping cart. One solution to this problem would be to have a version number attached to the server side shopping cart, and have a hidden field on the client. When the user presses checkout in the shopping cart, the versions are checked on the server. If the version information matches, the user is moved to checkout, otherwise they are presented with the checkout screen containing all the information, and a message stating that the shopping cart had been updated.

Scenario: A common business problem that may arise is when a user is entering data into a form which contains a drop-down list. The drop-down list is populated by another screen in the application and does not currently have the value the user needs. The user may open a new browser window, and navigate to the screen where they add new values to the drop-down. Once they have saved the record, they can close the new window. When they get back to the original screen, they can refresh the browser to get the new value to appear in the drop-down. If the application is using AJAX robustly, the refresh may either be automatically or the screen may have a button which refreshes the drop-down list while preserving the rest of the users work.What happens when two windows modify and save the same record?

Last Write Wins
This method says that whatever data is saved last is what will be in the database. This is the simplest solution, and generally happens by default if the situation has not been thought through.

The drawbacks to this method are:
The user is overriding information they have not yet reviewed, and may be clearing out information they were not trying to edit (e.g. The first write may put in a middle name, and the second write was meant to add a phone number, but also clears out the middle name)

If the first user deletes the record, the second user may not be informed that their update was discarded. If the database uses active flags to denote deleted records, the second update may also inadvertently restore the record.

First Write Wins
This method requires a time stamp or versioning field on the records being updated. If the user attempts to update a record, and the current time stamp or version does not match the value provided in the update request, the update fails. This ensures that the user must have been viewing the same data they are updating.

The drawbacks to this method are:
If the user must enter large amounts of data to update the record, it not only increases the probability the record will be updated while they are working on entering the data, but also means they will have to re-enter all the data once they have refreshed the data on the screen.

If an automated process is also updating the record, it may be very difficult for a user to update the record. This issue can be solved through the design of the software, but does need to be considered.

A smart write is a combination of “first write wins” and “last write wins”, but it uses a review / confirmation process to validate the write. Initially the process works like “first write wins”. If the write fails due to being out of sync, the user receives an error message, but the screen is recreated with the data the user had entered. The user then has a chance to review the record, and override the existing record. There are several methods of allowing the user to review the current record:

If the application is written to allow bookmarking, the user could review the current record by pressing ctrl+n (opening a new instance of the browser), and toggle between the two screens. This is the easiest solution from the programming aspect, but also the most error prone, and least user friendly.

The application could present side-by-side editors with the original data in one of the editors, and the new data in the other editor. The original data should be presented in read-only mode while the new data should be read-write. The fields containing differences should also be highlighted in some way. This is a method works well if the two editors will fit on the screen side-by-side.

If the two editors will not fit side-by-side on the screen, another option would be to put the two editors in a tab control, with one tab containing the editor with the original data in read-only mode, and the second tab containing the editor with the modified data. Again, the modified fields should be highlighted.

The editor could be written to show original values around the data entry field (to the left, right, top, or bottom). A control could also be added to automatically override the modified value with the value from the database for an individual field.

Record Locking
This technique allows the user to take ownership of a record to attempt to avoid the overwriting issues. When the user has multiple windows open, this technique no longer solves the problem, although it does limit the issue to a user overwriting their own data.

Drawbacks to this technique include:

  • Complicated implementation
  • Records get “hung” in a locked state until the lock times out
  • If the screen is set up to automatically renew the lock, the record may get locked indefinitely
  • If the screen is not set up to automatically renew the lock, the user must manually confirm retaining the lock on a regular basis
  • The less often the user has to confirm retaining the lock the longer the lock will take to time out

Smart Write + Soft Record Locking
This technique combines the functionality of a “smart write” with the ability to see who else is working on a record. Some implementations may allow a user to see the in-process changes of another user.

Proper Use of the Session Object
The session object resides on the server and is associated with an instance of a browser. Generally this association is equivalent to a user on a computer. The exceptions to this rule are when multiple types of browsers are open on the same computer (e.g. Safari and IE), and some very old versions of IE will start separate sessions when not started from an existing instance. Since the connection is not always persevered between page requests, it is not possible for the web server to associate the session with the connection, therefore a temporary cookie is used as an identifier when communicating with the server to identify the session. This means that there may be multiple windows associated with a single session object on the server. The session object is a good place to put information such as login credentials, and user specific settings. Using custom classes to hold the data will make code much more readable, efficient, and will avoid many run-time errors. This technique will also allow you to make multi-threaded calls more efficiently.

The session object should NOT be used to directly store page data or page state information.

Scenario 1: A user is editing record X, so it is retrieved from the database and stored in the session object. After the user modifies the record they click save, and the record is retrieved from the session object, populated with the new data and saved back to the database. This is a very efficient way of updating a record, except it has a major bug as demonstrated in Scenario 2.

Scenario 2: A user is editing record X so it is retrieved and stored in the session object. They then get a call and a change needs to be made immediately to record Y. The user does not want to lose their work on record X so the start a new window, navigate to record Y, which loads record Y into the session object (replacing record X). The user then modifies record Y and saves their changes to the database. Now they close out the new screen and return to editing what they believe to be record X in the original window (all of record X’s data is still in that window). When the user makes their changes and saves the record, the record they pull from the session object is record Y, which gets populated with all the data from record X, and saved back to the database. The result of all this is record X is never updated, and record Y ends up getting updated with the data meant for record X, and record Y’s data is discarded.

*NOTE: There are techniques which cache data effectively within the session object, this statement is meant for data object cached directly on the session object.

Delay writing to the database.
Sometimes it may be necessary to spread data entry over several screens. When there is too much information to display on a single page, it is common practice to use a tab group to display the information. Data entry wizards are also examples of multiple screens being used for data entry. When using multiple screens to gather data for a record, it is good practice to gather all the data before writing the record to the database. A user may change information in the first tab, change to the second tab, and change some more information, and then change their mind about updating the record, and close out the screen. If the application is writing to the database before all the information is gathered, they would have updated the information in the first tab even though they never saved the record. When using a wizard, the record may not be valid until the wizard is complete, so writing to the database is not possible. To save the data between the screens, the application can:

Store the information in hidden variables
Each of the fields on the non-shown screens can have their own hidden input, but lists within the wizard must be handled carefully

The view state (C# and VB.net) can be used to store an object which contains the data from the wizard.

Store the information in the session object.
An object is created to store the information from the wizard
A unique identifier is generated to identify the object within the session object

The unique number is placed in a hidden field on the page
When the page is posted, the object is looked up by the identifier, and updated based on the posted data

*NOTE: This technique does not save the information if the session times out.
*NOTE: A large number of users on the server using this functionality may put a strain on the server due to memory constraints if hard-drive caching is not implemented in conjunction with this method.

Multi-Threaded Application
A thread is a process which can run without blocking the main execution of a program. Imagine a scenario at home. Two kids need to be taken to practice, one to football, the other to baseball. One solution would be loading both kids into the car, dropping the first kid off at football practice and then taking the second kid to baseball practice. This is the single threaded method of solving the problem (you are the main thread doing all the work). The next approach would be to ask your spouse to take one of the kids to practice. This is the multi-threaded approach. In this scenario you are still the main thread doing part of the work, and your spouse is the new thread which takes over part of the work. There is another scenario where you ask your spouse to take one of the kids to practice and ask your neighbor who has a kid on the same team to take the other kid to practice because you have to go to work. While this may not be the ideal parenting style, it is very efficient. This is the optimized multi-thread approach.

Even if a web based application never creates and executes a thread, every web-based application is multi-threaded. When a web-browser is communicating with a server, it creates multiple threads in order to connect to the server multiple times so it can download the main html page, images, style sheets, etc. simultaneously. This allows the browser to show the page as efficiently as possible since no single resource (except possibly the HTML) can block the rest of the page from being processed. Multiple browsers, whether they are on the same machine, or on different machines, will create separate threads on the web server. If the application is not designed as a multi-threaded application, it may have serious consequences which will be VERY difficult to diagnose.

Do not assume the user is using a browser
This goes beyond not assuming your users are using a particular browser. A power user may not be using a browser at all. A power user may write an application which reads your website, and posts data back. If written correctly, it is impossible to determine the difference between this type of user and someone using a browser. The reason is, the only things your server knows about a client machine (other than networking information such as IP address) is what the client decides to share. Don’t be too alarmed by this, because most of the time it is not malicious hacking. Plus, if someone has taken the time to write a program to automate your website, it means they see value within your website.

What this means is, even though your website may validate all the users input on the screen before letting the data post back to the server, it does not mean that all the data being posted back to your server is valid. Something as simple as the user disabling JavaScript on their browser could also cause your server to received invalid data.

Data validation is important on the webpage before the page is allowed to post to the server because it is more efficient. The user does not have to wait for a page to reload to see if they missed a field, or typed something incorrectly. It also keeps some bad requests off your server. The fewer requests the server must handle per user, the more users the server can support. This level of validation makes the website “pretty”, but does not make it secure.

Validation on the server is what makes your website secure, and helps ensure valid data in the database. If validation fails on the server side, the page should be presented back to the user the same as if the validation had occurred on the client side through JavaScript. You cannot assume that a page that gets past the client-side validation (JavaScript), but fails server-side validation is an attack. A user may have JavaScript disabled by default on their browser until they believe they can trust a site. If your website requires JavaScript in order to show up, you are requesting your customers trust you before giving them any information about you.

The .Net framework currently defaults to disallowing certain characters to be submitted from a web-page. The idea is to disallow characters which could be used to hack into a database driven website. This option should NOT be enabled. An application does need to be guarded from hacking attempts, but this option is a way of avoiding instead of solving the problem. If this option is enabled and your user tries to send you a message that says “My server is down and it’s costing me money” your website will respond with an error message because it sees the single tick (‘) as a hacking attempt. If you do not know how to guard against hacking attempts, contact a developer or development company such as Bunch Consulting who can help. There are also several books and websites available if you prefer to research the subject.

If you have any questions about the subjects covered in this entry please contact us and we will try to answer your question as quickly as possible.