April, 2009

Posts
  • Eric Gunnerson's Compendium

    HealthVault XPath Explorer

    • 4 Comments

    By default, when a query is made to HealthVault, it returns all instances of a specific type. If you wish to filter to a subset of those instances, you can specify some properties in the HealthRecordFilter class. For example, you can set the CreatedApplication property to filter on the application that created the health record item.

    The filter properties, however, only works for properties that are shared across all data types. If you want to filter based on properties that are data-type-specific, you can do that by setting the XPath property to an appropriate XPath query.

    Creating that query is a bit inconvenient – perhaps a lot inconvenient – so I wrote a little utility that you can use to easily create an xpath query.

    You can find the code here.

    Make a copy of the HelloWorld sample, put the two files into it, and run the sample.

  • Eric Gunnerson's Compendium

    Introduction to HealthvaultDevelopment #11: Data filtering

    • 2 Comments

    The users are unhappy. The weight tracking application worked pretty well initially, but now that they’ve been using it daily for a few months, it’s showing them too much information. They would like it to show the recent results.

    That will take us into filtering…

    Filtering is done using the aptly-named HealthRecordFilter class. Thus far, we have only been using this class to filter to data that has the weight type id. In this episode we will explore additional ways to perform filtering.

    Common Data Filtering

    There are some properties that are shared across all data types. This section discusses filtering on those items.

    Filtering based on the number of items

    The simplest thing we can do is to only fetch a specific number of items rather than all of them. First, we add the following checkbox before the c_tableWeight table in default.aspx:

    <asp:CheckBox ID="c_CheckboxLast5Items" runat="server" Text="Last 5 items only" AutoPostBack="True" /><br />

    and then we change the filter definition in default.aspx.cs to:

    filter.View.Sections |= HealthRecordItemSections.Audits;
    if (c_CheckboxLast5Items.Checked)
    {
        filter.MaxItemsReturned = 5;
    }

    If you run this, when you click the checkbox you will only see the last 5 weight measurements.

    <aside>

    The HealthRecordItemCollection class implements lazy fetching of results. It will fetch chunks of instances at a time, going back to the server when it needs another chunk. The chunk size is set by the MaxFullItemsReturnedPerRequest property of the filter, and is 30 by default.

    This is transparent to the calling application, and the default value is usually fine.  Decreasing the value reduces the amount of work that the server has to do when processing each chunk, and might be required if your application deals objects that have significant amounts of data in them. This requires more trips to the server to fetch data, however, which will have performance implications.

    Increasing the value reduces the number of trips to the server to fetch all the data, but there is a possibility that the longer operations may result in a timeout.

    </aside>

    Filtering based on dates

    We can also filter based on the 

    First, add a checkbox above the table that allows the user to toggle this setting. You can do that through the designer or by adding the following before the c_tableWeight table:

    <asp:CheckBox ID="c_CheckboxLast3MonthsOnly" runat="server" Text="Last 3 months only" AutoPostBack="True" /><br />

    and the following is added to the filter definition:

    if (c_CheckboxLast3MonthsOnly.Checked)
    {
        filter.UpdatedDateMin = DateTime.Now - new TimeSpan(30, 0, 0, 0);
    }

    Filtering based on application id

    In a previous episode, we added some code to fetch the name of the application that last updated the data in HealthVault. We can filter on the application that last updated this data item so we only retrieve that items that our application retrieved (in general, apps should try to read all the data a user has, but it may make sense to only read this subset at times).

    This is done with the following:

    filter.UpdatedApplication = ApplicationConnection.ApplicationId;

    Adding the checkbox and the appropriate logic is left as an exercise to the reader.

    Type-Specific Filtering

    Filtering on a value that is specific to a type – the value of a weight measurement, the name of a medication is a bit more complex. The type-specific data for an instance is stored in HealthVault XML, so a filter needs to be able to find a specific piece of data inside of a larger chunk of XML and then compare it to a desired value.

    This is done using a query language that is known as XPath. To write an xpath expression for a specific HealthVault data type requires that you understand that XML format that is uses to store the information, which either requires getting the XML for a specific instance (by calling GetItemXml() on the instance), or understanding the XSD schema for the data type.

    To make this easier, I wrote the HealthVault XPath Explorer. This utility will let you easily walk the XML for instances that are in a specific HealthVault record, though you will have to figure out how to write the condition yourself. There are a number of good XPath tutorial available on the net.

    For our application, if we want to only return items where the weight value is less than 50 kilograms, we can use the following:

    filter.XPath = "/thing/data-xml/weight/value/kg[.> 50]";

    In the “[. > 50]”, the “.” refers to the current node, so it means “kg > 50”.

    Automatic user sign in

    You may have noticed that our demo app requires us to sign in every time we run it. This behavior is configurable:

    1. Go to the application configuration center
    2. Select the demo application
    3. Go to the “Misc” tab
    4. Toggle the “automatic user sign-in” radio button to “yes”
    5. Set a sign-in duration in seconds (I chose 3600).
    6. Click “Make changes”.

    That will start the configuration change process. Within 30 minutes, the update will make it to the servers, and a new “stay signed in” checkbox will appear on the log in page for the application.

    Next Time

    Next time we'll modify our application to work for the whole family.

  • Eric Gunnerson's Compendium

    Progressio per Patientia

    • 2 Comments

    "Progress through suffering"

    I have a friend (perhaps "riding acquaintance" is a more accurate term) named "Elden Fat Cyclist". Actually, that's his stage name. His real name is "Harold Fat Cyclist".

    Harold has been involved in Livestrong for a while and - for reasons that will become obvious if you read his blog - this year has decided to organize "Team Fat Cyclist", to try to win the team competition of the Livestrong challenge.

    This year, Livestrong has decided to hold a ride in Seattle. Their goal is apparently to do a shortened version of a Tour de France mountain stage, with an advertised 7900' of elevation gain over the 101 miles. That would, AFAIK, set a new standard for centuries in these parts, with the ever-popular (many would say "over-popular") Flying Wheels Century clocking in at 3500', and even the difficult 7 Hills century at only 7000'.

    Or, to put it another way, this ride will involve a significant amount of pain and suffering. Since signing up for rides that are harder than I should is a bit of a tradition for me (not to mention being a tradition for Harold), I signed up last week.

    That's where you come in.

    The event is a fundraiser for cancer research, and I'm looking for people to sponsor me in this undertaking.

    For the first $250 that's donated, I will match every dollar, and then Microsoft will match my dollar. So, if you donate $10, the total will be... well, it will be more than I can calculate on Sunny Seattle Spring Sunday.

    If you can spare some money to help out a worthy cause (cancer research, not me suffering), please head on over to my fundraising page.

Page 1 of 1 (3 items)