HealthVault Hello World

There have been a few requests for a HealthVault introduction that is simpler than the SleepJournal and FittrakLite ones, so I've create a simpler "Hello, World" sample that will show up in the SDK sometime in the near future.

I thought I'd walk you through the steps that I used, and talk about the code...

Step 1: Creating the project

In Visual Studio 2005, I chose File->New->Web Site, chose "ASP.NET Web site", and then entered a name and location for the site. I'm going to keep it as a "File System" website to make things easier for me.

I can now hit F5, and an "untitiled page" will come up in the browser:

Step 2: Derive from HealthServicePage

In default.aspx.cs, I rename the application class to HelloWorldPage, and set the base type to HealthServicePage. When I rename the application, I also change the Page tag in default.aspx so that it inherits from this new name as well.

To be able to reference that page, I need to add the two HealthVault assemblies to the project. I right-click on the project, choose "Add Reference", and browse to "C:\Program Files\Microsoft HealthVault\SDK\DotNet\Assemblies", and add Microsoft.Health.dll and Microsoft.Health.Web.dll to the project.

I also add:

using Microsoft.Health;
using Microsoft.Health.ItemTypes;
using Microsoft.Health.Web;
using System.Collections.Generic;

to the C# file, which gets the application compiling.

Step 3: Add entries to the Web.config file

The HealthVault classes look in the web.config file to find a number of items - where the HealthVault servers are, what application id to use, etc. We need to add those entries into our file.

Rather than include them here, I'll recommend that you grab them from one of the SDK examples. Perhaps the HelloWorld one if it is there.  After you copy it over, go find the section where that looks like this:

<

add key="WCPage_ActionHome" value="default.aspx"/>
<add key="WCPage_ActionAppAuthSuccess" value="default.aspx"/>
<add key="WCPage_ActionSignOut" value="SignedOut.aspx" />

These keys control the redirect after authorization. Make sure that the first two point to the main page of your application, and you can leave the third one alone for now.

These values are only used when talking to the development server (www.microsofthealthbeta.com). When you eventually deploy an application, these are hardcoded on the server so that anybody using a specific application ID always redirects to the same URL.

We will also need to add a "redirect" page (ie redirect.aspx and redirect.aspx.cs). I suggest stealing this directly from one of the samples, and adding it to your project. You will note that the NonProductionActionUrlRedirectOverride key in web.config already points at redirect.aspx.

Step 4: Add a master page

Yes, I know, I don't strictly need a master page, but it makes things a bit simpler, so go ahead and add one, call it HelloWorld.master, and modify redirect.aspx and default.aspx to reference it.

Step 5: Test the app

Hit F5. If everything is working fine, you will log into HealthVault, authorize the application (if you haven't authorized that app before), and then be redirected back to your application page.

That gets us "up and running", now we can start doing something useful.

Step 6: Display the name of the user

I'll start with a little bit of code that will display the name of the user. I'll add a control to the page:

Name:

<asp:Label ID="c_UserName" runat="Server"/><br />

The HealthServicePage that we're derived from has a property named PersonInfo, so we'll grab the name from there:

c_UserName.Text = PersonInfo.Name; // added to the Page_Load method

Step 7: Display the birth year of the user

Add a control on the page:

Birth Year:

<asp:Label ID="c_BirthYear" runat="Server"/><br />

And now fetch the value from HealthVault. To do that, we will use the HealthRecordSearcher class. We create one using the following:

HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher();

Note carefully the "SelectedRecord" part. Because HealthVault supports one user have access to more than one health record - perhaps I have access to my daughter's record - we need to use the current "selected" one.

Next, we need to constrain the search to get only the information we want:

HealthRecordFilter filter = new HealthRecordFilter(Basic.TypeId);
searcher.Filters.Add(filter);

This code will return all instances of the "Basic" type in the health record. We could further constrain the query - say, to a specific date range - by adding other items to the searcher.Filters collection.

Finally, we need to actually fetch the values and display them:

HealthRecordItemCollection items = searcher.GetMatchingItems()[0];

Basic basic = (Basic) items[0];
if (basic != null && basic.BirthYear.HasValue)
{
c_BirthYear.Text = basic.BirthYear.ToString();
}

I'll simplify the fetching by writing a generic method:

T GetSingleValue<T>(

Guid typeID) where T : class
{
HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher();
HealthRecordFilter filter = new HealthRecordFilter(typeID);
searcher.Filters.Add(filter);

HealthRecordItemCollection items = searcher.GetMatchingItems()[0];
return items[0] as T;
}

And then I can simply write:

Basic basic = GetSingleValue<Basic>(Basic.TypeId);

to fetch the value.

Step 8: Insert values into HealthVault

I'll add a button on the page:

<asp:Button ID="c_AddHeightEntry" Text="Add Height Entry" runat="server"/>

and the following code to the Page_Load() method:

if (IsPostBack)
{
AddHeightEntry();
}

I'll the write the method to do the add:

void AddHeightEntry()
{
    Length value = new Length(2.0);
    Height height = new Height(new HealthServiceDateTime(DateTime.Now), value);

PersonInfo.SelectedRecord.NewItem(height);
}

I create an instance of the Height class, and then call NewItem() to save it to HealthVault. You can go to the HealthVault user page if you want to see the Height values.

Step 9: Fetch and display the Height values

Note that this is the simplified version of how to fetch and display values. In many cases, you may want to use the cached approach featured in the HealthAndFitness sample app.

I'll add a table to the page:

<asp:Table ID="c_HeightTable" runat="Server"/>

A generic method to fetch the items:

List<T> GetValues<T>(Guid typeID) where T : HealthRecordItem
{
HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher();
HealthRecordFilter filter = new HealthRecordFilter(typeID);
searcher.Filters.Add(filter);

HealthRecordItemCollection items = searcher.GetMatchingItems()[0];
List<T> typedList = new List<T>();

foreach (HealthRecordItem item in items)
{
typedList.Add((T) item);
}

return typedList;
}

which is very much like the single-element fetch, except that it iterates through all the items, and then code to populate the table:

void PopulateHeightTable()
{
c_HeightTable.Rows.Clear();

TableRow headerRow = new TableRow();
TableHeaderCell headerDateCell = new TableHeaderCell();
headerDateCell.Text = "Date";
headerRow.Cells.Add(headerDateCell);

TableHeaderCell headerHeightCell = new TableHeaderCell();
headerHeightCell.Text = "Height";
headerRow.Cells.Add(headerHeightCell);
c_HeightTable.Rows.Add(headerRow);

List<Height> heightMeasurements = GetValues<Height>(Height.TypeId);
foreach (Height height in heightMeasurements)
{
TableRow row = new TableRow();
c_HeightTable.Rows.Add(row);
TableCell dateCell = new TableCell();
dateCell.Text = height.When.ToString();
row.Cells.Add(dateCell);

TableCell heightCell = new TableCell();
heightCell.Text = String.Format("{0:F2}", height.Value.Meters);
rowCells.Add(heightCell);
}
}

And now, the app will display the values and add another one if you hit the add button.