none
Usage of GetTransformedItems()

    Question

  • In the help documentation for the HealthRecordSearcher.GetTransformedItems() method -
    http://msdn.microsoft.com/en-us/library/microsoft.health.healthrecordsearcher.gettransformeditems.aspx

    under the Parameters section, the string transform parameter is described as "A URL to a transform to run on the resulting XML. This can be a fully-qualified URL or the name of one of the standard XSLs provided by the HealthVault system. "

    Furthermore, under the Remarks section, it says- "...The transform can be specified as a XSL fragment or a well-known transform tag provided by the HealthVault service. If a XSL fragment is specified, it gets compiled and cached on the server. "

    In our HealthVault web application, we call this method with a string argument containing the actual xsl template code (not a url to the xsl file) and it works fine in PPE.

    Is this usage of the method valid? and supported by Microsoft? We want to ensure that it will continue to be supported in future.
     

    Second question: Is there a way to pass xslt parameters for the server-side transformation done by the GetTransformedItems() method call ? Just like the HealthRecordExporter class allows us to do via its TransformArgumentList property.


    Manish

    Thursday, March 15, 2012 10:42 PM

Answers

  • This mechanism of passing an XSL fragment is supported and will continue to be supported. There are a few minor limitations. For instance, you can't use embedded script in the XSL.

    You cannot specify an argument list to the transform. Unlike the HealthRecordExporter which runs on the client, this transform is run on the server. We do pass a common set of parameters to the transform though:

    • currentDateTimeUtc - the current UTC date and time
    • requestingApplicationName - the name of the application that called HV
    • countryCode - the two-letter country code taken from the culture of the request
    • languageCode - the two-letter language code taken from the culture of the request
    • personName - the name of the person specified by the person-id in the auth-token of the request
    • recordName - if the request was for a method that takes the record-id in the header, the name of the record will be provided

    One of the disadvantages to having the server perform the transform is that if you are making a GetThings call for lots of data, the maxFullThings for a request might be exceeded, and unless your transform takes this into account you might miss data that was only partial when the transform was run. In this case you are better off using HealthRecordExporter, it will page down the data, assemble it on the client, and then run the transform. It will also allow you to pass parameters and embed script. The disadvantage is that you can't reduce the amount of data coming from the server which is often why the "final-xsl" is used.


    Jeff Jones Technical Lead HealthVault Development Team

    Friday, March 16, 2012 2:51 PM

All replies

  • This mechanism of passing an XSL fragment is supported and will continue to be supported. There are a few minor limitations. For instance, you can't use embedded script in the XSL.

    You cannot specify an argument list to the transform. Unlike the HealthRecordExporter which runs on the client, this transform is run on the server. We do pass a common set of parameters to the transform though:

    • currentDateTimeUtc - the current UTC date and time
    • requestingApplicationName - the name of the application that called HV
    • countryCode - the two-letter country code taken from the culture of the request
    • languageCode - the two-letter language code taken from the culture of the request
    • personName - the name of the person specified by the person-id in the auth-token of the request
    • recordName - if the request was for a method that takes the record-id in the header, the name of the record will be provided

    One of the disadvantages to having the server perform the transform is that if you are making a GetThings call for lots of data, the maxFullThings for a request might be exceeded, and unless your transform takes this into account you might miss data that was only partial when the transform was run. In this case you are better off using HealthRecordExporter, it will page down the data, assemble it on the client, and then run the transform. It will also allow you to pass parameters and embed script. The disadvantage is that you can't reduce the amount of data coming from the server which is often why the "final-xsl" is used.


    Jeff Jones Technical Lead HealthVault Development Team

    Friday, March 16, 2012 2:51 PM
  • Thank you Jeff. Your explanation is much appreciated.

    In fact, we're using the personName, recordName and currentDateTimeUtc parameters currently in our xsl template to produce part of the output.

    Regarding your comment- "...if you are making a GetThings call for lots of data, the maxFullThings for a request might be exceeded, and unless your transform takes this into account you might miss data that was only partial when the transform was run".

    We currently use the following limits from our web.config file and these values are used when setting the filters for the HealthRecordSearcher. The reason we set both properties to the same value is that we do not want any partial items. Is there some guidance on what would be a good limit to use? Are there internal limits within HealthVault on MaxItemsReturned or MaxFullItemsReturnedPerRequest that may be less than 500 and therefore may overwrite our application limits?

    <add key="MaxFullItemsReturnedPerRequest" value="500"/>
    <add key="MaxItemsReturned" value="500"/>

    The way our query works is that we are simulating a paged query by breaking up the original query (with a potentially large date range) into multiple queries (each with a smaller date range), thereby, minimizing the likelihood that we get more than 500 items.

    Regarding - "The disadvantage is that you can't reduce the amount of data coming from the server which is often why the "final-xsl" is used."

    You're right on. This is the reason why we could not use HealthRecordExporter class as much as we'd love to. We have no control over the volume of xml being returned from the server because HealthRecordExporter.ExportItems() internally uses HealthRecordSearcher which constructs an entire collection of HealthRecordItems. If not for that one fact, it has everything we need.

    Thanks again. Very helpful.


    Manish

    Friday, March 16, 2012 7:30 PM
  • You should call GetServiceDefinition (HealthServiceConnection.GetServiceDefinition), which will return all the public configuration items for the service. One of these is called "maxFullThingResultsPerGroup".  Use the value of this config item when setting your MaxFullItemsReturnedPerRequest and MaxItemsReturned.

    Jeff Jones Technical Lead HealthVault Development Team

    Friday, March 16, 2012 7:40 PM
  • Jeff, I tried that. That particular max setting is set to 240, so looks like our application setting of 500 would not have been honored by the service. Thanks for your tip, I would have missed that without your help.

    Looks like there are a lot more max* limits returned by the Service Definition call. See image below.

    GetServiceDefinition configuration values

    I wonder what impact the rest of the max* values will have. Will research this more and get back to you if I run into questions. Have a great weekend!


    Manish

    Friday, March 16, 2012 8:46 PM
  • Here's a stab at the max* values:

    • maxAlternateIdsPerRecord - new 1202 feature (http://blogs.msdn.com/b/healthvault/archive/2012/02/10/healthvault-1202-release.aspx) allows for alternative IDs for record that an application can specify. This setting limits how many alternate IDs can be specified for a record.
    • maxBlobChunkSizeBytes - when streaming blob data to HV it must be parcelled into chunks no greater than the size of this configuration. HV will put the chunks together into the full blob when it gets committed through the PutThings method.
    • maxBlobSizeBytes - the largest size allowed for an assembled blob.
    • maxCredentials - maximum number of credentials allowed per person
    • maxFullThingResultsPerGroup - each GetThings call can have multiple groups, each specifying a different filter and view. This indicates the maximum number of full things returned per group. If more things exist, they will be returned as partial things (just type-id and key).
    • maxGetThingsQueryGroups - the number of groups (filter/views) allowed to be specified in a single GetThings call.
    • maxInitialRecords - the maximum number of authorized records returned during a GetThings call. GetAuthorizedRecords can be called to get the rest.
    • maxInlineBlobSizeBytes - if blobs are specified by encoding in the XML of the thing rather than streaming through the blob handler, this is the maximum size of the blob.
    • maxPartialThingResultsPerGroup - once the maxFullThingResultsPerGroup is hit on a GetThings call, only partial (type-id and key) are returned. This specifies the maximum number of partial things returned.
    • maxPersonInfosPerRetrieval - the maximum number of PersonInfo's returned from a GetAuthorizedPeople request
    • maxRequestUncompressedSizeBytes - the maximum size in bytes of any single XML request to HealthVault.
    • maxResultsPerVocabularyRetrieval - the maximum number of results returned from the SearchVocabulary method
    • maxVocabItems - the maximum number of vocabulary items returned from the GetVocabulary method

    Ali has been working on designing improvements for our developer experience. I'll be sure he makes documentation of all the public settings available at some point.


    Jeff Jones Technical Lead HealthVault Development Team

    Friday, March 16, 2012 9:03 PM
  • Thanks Jeff, this is great information. Looks like none of the other max settings will affect our application at this point. We're using only two filters- so maxGetThingsQueryGroups shouldn't be an issue.

    A related issue I ran into- if for a given query, the maxFullThingResultsPerGroup limit is hit, the app will get back only as many items as that limit dictates (240 currently). And in our case, there will be no partial items because we set MaxFullItemsReturnedPerRequest and MaxItemsReturned properties of the filter to the same value. What about the remaining items over the 240 limit? Is there a way to get those? I couldn't find anything in the SDK Help or blogs or this forum.

    Manish


    Manish


    Saturday, March 17, 2012 3:46 PM
  • You'll never get more items than MaxItemsReturned (partial or full). So if you want to be able to page down more data as needed, you'll need to set MaxItemReturned greater than MaxFullItemsReturnedPerGroup (or not set it). That way you'll get the IDs of all the other items that match the filter which will allow you to retrieve them later.


    Jeff Jones Technical Lead HealthVault Development Team

    Saturday, March 17, 2012 6:03 PM
  • I understand but that won't quite help in our scenario because then we'll have to go back to the HealthVault platform to fetch additional items by their item IDs. Which could be potentially hundreds of IDs.

    And a bigger issue is - whatever we set MaxItemsReturned to may not be enough. e.g. What if we set MaxItemsReturned to 300 and there are in fact 301 items matching the filter criteria? We'll get back 240 full items (since that's the max setting imposed by the service on maxFullThingResultsPerGroup) and we'll get (300 - 240) = 60 partial items. We'll miss the 301st item, correct?


    Manish

    Sunday, March 18, 2012 6:28 AM