Introduction to HealthVault Development #6 – Fixing a mistake
After we’ve released our application, some of our users complained that they accidentally entered an incorrect weight, and would like to have a way of fixing it.
We will therefore extend our application to be able to update a weight. We’re going to do that by creating a separate edit page (editing in-line would be nicer, but this way is simpler).
For the update page to know which weight it should be editing, we need a way to uniquely identify a specific weight instance. Every item that is stored in a HealthVault record has a property named Key of type HealthRecordItemKey. That type has two properties:
- A guid named Id that uniquely identifies the instance.
- A guid named VersionStamp that I’ll discuss in a little bit.
For each Weight that is stored in our table, we’ll create a hyperlink to the update page that passes the Id. We do this by placing creating a HyperLink object and adding it to the table, and in this case there’s already a helper in the project that does that. So, we add the following after the call to AddCellsToTable():
We also add a blank column header so the table doesn’t look weird:
AddHeaderCells(c_tableWeight, "Date", "Weight", "BMI", "");
That will give us a link to UpdateWeight.aspx. If you open that file, you’ll see that it has a few labels for displaying the current data, a place to enter the new weight, and an Update button.
We need to write the code to fetch the Weight instance that the user wants to edit. We do this in the Page_Load() method in UpdateWeight.aspx.cs. First, we convert the Id from a string to a guid and stash it away for later:
_idToUpdate = new Guid(id);
Now we fetch the Weight instance. In our previous code, we used a filter to find the set of items that met a specific set of criteria, but in this case we’re looking to get a specific instance of the Weight type. We do that by calling GetItem():
Weight weight = (Weight)
The _idToUpdate argument specifies which item we want to fetch, and the second one specifies what part of the object to fetch.
Each HealthVault instance has a fair amount of data and metadata associated with it, and for performance reasons, applications should typically fetch only a subset of the sections.
The sections are defined by the HealthRecordItemSections enumeration, which has the following items in it:
This section contains information about when an item was created or updated, which application and person performed the update, and when it happened. If it is passed, the Created and LastUpdated properties on the object will be populated.
This section contains the core information for the object, including the EffectiveDate, State, Flags, IsPersonal, IsDownVersioned, and IspVersioned properties.
An application can use the EffectivePermissions information to determine what operations it is authorized to perform on an object.
This section contains information that is either auxiliary to the main purpose of the object, or information that is large and would not always be needed.
This section is similar to OtherData but provides stream-based access to the information
This section contains the HealthRecordItemSignatures property.
This section contains any textual tags that have been applied to the instance.
This section contains the type-specific information for the type. You will need to fetch this if you want to use any properties defined on the type.
The section information can also be specified on filtered queries using HealthRecordFilter.View.Sections.
Displaying the data
Now that the data is fetched, we can populate the values into the UI controls:
c_labelInstanceId.Text = _idToUpdate.ToString();
c_labelWeight.Text = weight.Value.DisplayValue.ToString();
Note that for the weight, we’re displaying exactly what the user originally entered by using the DisplayValue property.
Updating the weight value
The last task is to update the weight item, which uses a slight variation of the code we wrote to save the value in the first place. This goes in the MakeUpdate() method:
Weight weight = (Weight)
int weightInPounds = Int32.Parse(c_textboxNewWeight.Text);
weight.Value.Kilograms = weightInPounds / 2.204;
weight.Value.DisplayValue = new DisplayValue(weightInPounds, "pounds");
One of the challenges in any system that allows multiple applications to read/write data at once is maintaining data integrity. Specifically, with the above code, we need to make sure that that nothing in the instance changes between the time we fetch the value and when the update happens.
This is where the VersionStamp comes in. Whenever an instance is stored in HealthVault, the system creates a VersionStamp to store with it. In the update code, when the weight is fetched, it gets the current value of the VersionStamp. When UpdateItem is called, that version stamp is passed back to the platform. If it matches the current version stamp, then the platform knows that the object has not been modified, and the update operation is successful. If the version stamps do not match, the call to UpdateItem() will throw an exception, and the application will need to implement appropriate recovery methods to handle it.
After the update is performed, the code redirects back to the application’s main page.
Next time, we’ll talk about some perplexing data that is showing up for some of our users.