locked
Problem casting a HealthRecordItem to my custom wrapper type RRS feed

  • Question

  • We are inserting application specific types into HealthVault using the sample code presented here: http://msdn.microsoft.com/en-us/healthvault/bb968869.aspx

    Everything seems to be going fine until I try to retreive the item back from HV and cast it to our custom wrapper class.  The HVRecordItemCustomTypeWrapper class is derived from HealthRecordItem and is implemented just like the example.

    The specific exception is:
    "Unable to cast object of type 'Microsoft.Health.ItemTypes.ApplicationSpecific' to type ....HVRecordItemCustomTypeWrapper'."

    HealthRecordFilter filter = new HealthRecordFilter(MaximumItemLimit);
    filter.TypeIds.Add(new HVRecordItemCustomTypeWrapper().TypeId);
    HealthRecordSearcher searcher = _record.CreateSearcher();
    searcher.Filters.Add(filter);
    
    ReadOnlyCollection<HealthRecordItemCollection> searchResultsGroup = searcher.GetMatchingItems();
    HealthRecordItemCollection items = searchResultsGroup.Count > 0 ? searchResultsGroup[0] : null;
    
    if (items != null)
    {
        foreach (HealthRecordItem item in items)
        {
            // this throws an invalid cast exception
            HVRecordItemCustomTypeWrapper wrapper = (HVRecordItemCustomTypeWrapper)item;
            MyCustomObjectType hvPatientContext = wrapper.WrappedObject as MyCustomObjectType;
            if (hvPatientContext != null)
            {
                //.. do something
            }
        }
    }
    


    When looking at the item, I can see the xml for my object in the TypeSpecificData.  Why wouldn't I be able to cast the item back to the wrapper class?
    Monday, April 13, 2009 7:43 PM

Answers

  • The most common reason for this behavior is that you forgot to register the handler class for custom type with ItemTypeManager

    You should call the following to register your class (this call should happen before you call search - a good place to do this is global.asax's application start handler)

    ItemTypeManager.RegisterTypeHandler(new Guid("a5033c9d-08cf-4204-9bd3-cb412ce39fc0"), typeof(HVRecordItemCustomTypeWrapper ), true);

    Let me know if this fixes your issue

    Raj


    Raj HealthVault Developer Tool http://xray.getrealconsulting.com
    • Marked as answer by Kevin Noone Tuesday, April 14, 2009 5:50 PM
    Tuesday, April 14, 2009 10:47 AM

All replies

  • The most common reason for this behavior is that you forgot to register the handler class for custom type with ItemTypeManager

    You should call the following to register your class (this call should happen before you call search - a good place to do this is global.asax's application start handler)

    ItemTypeManager.RegisterTypeHandler(new Guid("a5033c9d-08cf-4204-9bd3-cb412ce39fc0"), typeof(HVRecordItemCustomTypeWrapper ), true);

    Let me know if this fixes your issue

    Raj


    Raj HealthVault Developer Tool http://xray.getrealconsulting.com
    • Marked as answer by Kevin Noone Tuesday, April 14, 2009 5:50 PM
    Tuesday, April 14, 2009 10:47 AM
  • It appears that you are defining an application-specific type, not a wrapper for an existing HealthRecordItem.  You should derive from ApplicationSpecific instead of HealthRecordItem and you need to register the class with ItemTypeManager.RegisterApplicationSpecificHandler().

    Jeff Jones
    Technical Lead, HealthVault, Health Solutions Group, Microsoft Corporation
    Tuesday, April 14, 2009 4:55 PM
  • Thanks Raj, I tried to register the type again but I still get the invalid cast exception.  Is the ItemTypeManager documented in more detail somewhere?  Even if that's not the issue, I'd like to understand more about what it's doing.

    More info that could be helpful...

    We are using master/child applications.  This shouldn't matter because the same child application that stored the object is trying to retrieve it.

    We are storing the object like this:
    HVRecordItemCustomTypeWrapper wrapper = new
     HVRecordItemCustomTypeWrapper(customObject) { When = new
     HealthServiceDateTime() };
    customObject.When = new HealthServiceDateTime(DateTime.Now);
    record.NewItem(wrapper);


    To reiterate, storage and retrieval work fine, it's just casting it back to the wrapper class that fails.
    Tuesday, April 14, 2009 4:57 PM
  • So the wrapper class needs to derive from ApplicationSpecific? 

    I was following the example here: http://msdn.microsoft.com/en-us/healthvault/bb968869.aspx which treats the wrapper as a HealthRecordItem.  The constructor of my wrapper class looks like this:
    public CustomHealthTypeWrapper(HealthRecordItemCustomBase wrappedInstance) :
    base(new Guid(ApplicationCustomTypeID))
    where ApplicationCustomTypeID is the TypeId of the ApplicationSpecific class.
    Tuesday, April 14, 2009 5:33 PM
  • I think the issue must be with RegisterTypeHandler() because the code is almost an exact copy of the HealthAndFitness example.  Would offline access have anything to do with it?  We are inserting the custom object online, and then accessing it offline.

    Edit: things are working now.  To elaborate, I didn't understand what RegisterTypeHandler() was doing.  We are inserting the custom type from one application and then reading it from another.  I didn't realize that the second application also needed to register the custom type.  It turns out that the type registration is for your application, and not something taking place in HV.

    Thanks for the help!
    Tuesday, April 14, 2009 5:44 PM