Пример #1
0
        protected override void ProcessRecord()
        {
            HealthClientApplication clientApp        = HvShellUtilities.GetClient();
            List <PersonInfo>       authorizedPeople = new List <PersonInfo>
                                                           (clientApp.ApplicationConnection.GetAuthorizedPeople());

            // Create an authorized connection for each person on the
            //   list.
            HealthClientAuthorizedConnection authConnection = clientApp.CreateAuthorizedConnection(
                authorizedPeople[0].PersonId);

            // Use the authorized connection to read the user's default
            //   health record.
            HealthRecordAccessor accessor = new HealthRecordAccessor(
                authConnection, authConnection.GetPersonInfo().GetSelfRecord().Id);

            HealthServiceRequest request =
                new HealthServiceRequest(accessor.Connection, "PutThings", 2, accessor);

            // Read the input file
            request.Parameters = System.IO.File.ReadAllText(Path.GetFullPath(FileName));
            request.Execute();
        }
        /// <summary>
        /// Retrieves a collection of key information for identifying and 
        /// describing the vocabularies in the system.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use for this operation. The connection
        /// must have application capability. 
        /// </param>
        /// 
        /// <returns>
        /// A collection of keys identifying the vocabularies in the system.
        /// </returns>
        /// 
        public virtual ReadOnlyCollection<VocabularyKey> GetVocabularyKeys(HealthServiceConnection connection)
        {
            string methodName = "GetVocabulary";
            HealthServiceRequest request = new HealthServiceRequest(connection, methodName, 1);

            request.Execute();

            ReadOnlyCollection<VocabularyKey> keys
                = CreateVocabularyKeysFromResponse(methodName, request.Response);
            return keys;
        }
        /// <summary>
        /// Deletes a request for a connection that has been made by the calling application but
        /// has not been validated by the user.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to HealthVault to use for this operation. 
        /// </param>
        /// 
        /// <param name="applicationPatientId">
        /// The application's identifier for the user which was used to create the connection 
        /// request.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// If <paramref name="applicationPatientId"/> is <b>null</b> or empty.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        /// 
        public virtual void DeletePendingPatientConnection(
            OfflineWebApplicationConnection connection,
            string applicationPatientId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");
            Validator.ThrowIfStringNullOrEmpty(applicationPatientId, "applicationPatientId");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "DeletePendingConnectRequest", 1);

            request.Parameters = "<external-id>" + applicationPatientId + "</external-id>";

            request.Execute();
        }
        /// <summary>
        /// Updates an existing pending package with a new application patient identifier.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The HealthVault connection to use for the operation.
        /// </param>
        /// 
        /// <param name="identityCode">
        /// The unique token that identifies the package.
        /// </param>
        /// 
        /// <param name="newApplicationPatientId">
        /// The new application patient identifier.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// If <paramref name="newApplicationPatientId"/>
        /// is <b>null</b> or empty.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        /// 
        public virtual void UpdateConnectPackageApplicationPatientIdForIdentityCode(
            OfflineWebApplicationConnection connection,
            string identityCode,
            string newApplicationPatientId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");
            Validator.ThrowIfStringNullOrEmpty(identityCode, "identityCode");
            Validator.ThrowIfStringNullOrEmpty(newApplicationPatientId, "newApplicationPatientId");

            StringBuilder requestBuilder = new StringBuilder(256);

            XmlWriterSettings writerSettings = new XmlWriterSettings();
            writerSettings.ConformanceLevel = ConformanceLevel.Fragment;

            using (XmlWriter writer = XmlWriter.Create(requestBuilder, writerSettings))
            {
                writer.WriteElementString("identity-code", identityCode);
                writer.WriteElementString("new-external-id", newApplicationPatientId);
            }

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "UpdateExternalId", 1);

            request.Parameters = requestBuilder.ToString();

            request.Execute();
        }
        /// <summary>
        /// Sets the application settings for the current application and
        /// person.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be authenticated. </param>
        ///
        /// <param name="requestParameters">
        /// The request parameters.
        /// </param>
        /// 
        /// <remarks>
        /// This may be <b>null</b> if no application settings have been 
        /// stored for the application or user.
        /// </remarks>
        /// 
        public virtual void SetApplicationSettings(
            HealthServiceConnection connection,
            string requestParameters)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "SetApplicationSettings", 1);

            request.Parameters = requestParameters;
            request.Execute();
        }
        /// <summary>
        /// Asks HealthVault to create a pending package for the application specified
        /// by the connection with the specified user specific parameters and the pre-allocated
        /// identity code.
        /// </summary>
        /// 
        /// <remarks>
        /// The password protected package supports 2 encryption algorithms, AES256 (recommended)
        /// and TripleDES. 
        /// <br/><br/>
        /// For AES256, the supported key size is 256 bits, the blocksize is 256 bits, the IV 
        /// length is 32 bytes.
        /// <br/><br/>
        /// For TripleDES, the supported key size is 192 bits, the blocksize is 64 bits, the IV 
        /// length is 8 bytes.
        /// <br/><br/>
        /// The encryption key should be derived using the answer, the salt, and the number of hash 
        /// iterations. The decryption will generate this key via the 
        /// <see cref="Rfc2898DeriveBytes"/> class, hence, encryption should use a similar or 
        /// identical process. To ensure case-insensitivity, the answer should be converted to its
        /// lower cased form using <see cref="String.ToLowerInvariant()"/> (culturally-agnostic) 
        /// prior to generating the derived key.
        /// <br/><br/>
        /// The algorithm used has the following parameters:
        /// <ul>
        ///    <li>Mode = CipherMode.CBC</li>
        ///    <li>Padding = PaddingMode.ISO10126</li>
        /// </ul>
        /// <br/><br/>
        /// The salt supplied is used as the salt to the derived key as well as the key to the 
        /// supplied HMAC. The salt should be at least 8 bytes long.
        /// <br/><br/>
        /// It is recommended that the number of hash iterations be at least 10000.
        /// </remarks>
        /// 
        /// <param name="creationParameters">
        /// The parameters to use when creating the package. 
        /// </param>
        /// 
        /// <param name="connectPackage">
        /// The pending connect package that the user will add to his/her record. 
        /// This package's
        /// <see cref="HealthRecordItem"/>'s <see cref="BlobStore"/> must be an encrypted 
        /// blob of xml that represents a list of HealthRecordItems. This xml blob
        /// must be a sequence of <thing/> elements, each wrapping the XML representation of a 
        /// single HealthRecordItem. Each <thing/> element may be generated by calling 
        /// <see cref="HealthRecordItem.GetItemXml()"/>.
        /// </param>
        ///         
        /// <returns>
        /// A token that the application must give to the patient to use when validating the
        /// connection request.
        /// </returns>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        ///
        public virtual string CreateConnectPackage(
            ConnectPackageCreationParameters creationParameters,
            PasswordProtectedPackage connectPackage)
        {
            Validator.ThrowIfArgumentNull(
                connectPackage,
                "connectPackage",
                "PackageCreatePPPMissingMandatory");

            HealthServiceRequest request =
                new HealthServiceRequest(creationParameters.Connection, "CreateConnectPackage", 2);

            request.Parameters =
                WriteConnectPackageParametersXml(
                    creationParameters,
                    connectPackage);

            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "CreateConnectPackage");

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath);
            return infoNav.SelectSingleNode("identity-code").Value;
        }
        /// <summary>
        /// Gets the permissions which the authenticated person 
        /// has when using the calling application for the specified item types
        /// in this  record.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        ///
        /// <param name="healthRecordItemTypeIds">
        /// A collection of unique identifiers to identify the health record  
        /// item types, for which the permissions are being queried. 
        /// </param>
        /// 
        /// <returns>
        /// Returns a dictionary of <see cref="HealthRecordItemTypePermission"/> 
        /// with health record item types as the keys. 
        /// </returns>
        /// 
        /// <remarks> 
        /// If the list of health record item types is empty, an empty dictionary is 
        /// returned. If for a health record item type, the person has 
        /// neither online access nor offline access permissions, 
        /// <b> null </b> will be returned for that type in the dictionary.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="healthRecordItemTypeIds"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If there is an exception during executing the request to HealthVault. 
        /// </exception>
        /// 
        public virtual IDictionary<Guid, HealthRecordItemTypePermission> QueryPermissionsByTypes(
            ApplicationConnection connection,
            HealthRecordAccessor accessor,
            IList<Guid> healthRecordItemTypeIds)
        {
            Validator.ThrowIfArgumentNull(healthRecordItemTypeIds, "healthRecordItemTypeIds", "CtorhealthRecordItemTypeIdsArgumentNull");

            Dictionary<Guid, HealthRecordItemTypePermission> permissions =
                new Dictionary<Guid, HealthRecordItemTypePermission>();

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "QueryPermissions", 1, accessor);

            for (int i = 0; i < healthRecordItemTypeIds.Count; ++i)
            {
                if (!permissions.ContainsKey(healthRecordItemTypeIds[i]))
                {
                    permissions.Add(healthRecordItemTypeIds[i], null);
                }
            }

            request.Parameters =
                GetQueryPermissionsParametersXml(healthRecordItemTypeIds);

            request.Execute();

            XPathNavigator infoNav =
                request.Response.InfoNavigator.SelectSingleNode(
                    GetQueryPermissionsInfoXPathExpression(
                        request.Response.InfoNavigator));

            XPathNodeIterator thingTypePermissionsNodes =
                infoNav.Select("thing-type-permission");

            foreach (XPathNavigator nav in thingTypePermissionsNodes)
            {
                HealthRecordItemTypePermission thingTypePermissions =
                    HealthRecordItemTypePermission.CreateFromXml(nav);
                permissions[thingTypePermissions.TypeId] = thingTypePermissions;
            }
            return permissions;
        }
        /// <summary>
        /// Gets the <see cref="HealthRecordInfo"/> for the records identified
        /// by the specified <paramref name="recordIds"/>.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be authenticated. </param>
        ///
        /// <param name="recordIds">
        /// The unique identifiers for the records to retrieve.
        /// </param>
        /// 
        /// <returns>
        /// A collection of the records matching the specified record 
        /// identifiers and authorized for the authenticated person.
        /// </returns>
        /// 
        /// <remarks>
        /// This method is useful in cases where the application is storing
        /// record identifiers and needs access to the functionality provided
        /// by the object model.
        /// </remarks>
        /// 
        public virtual Collection<HealthRecordInfo> GetAuthorizedRecords(
            ApplicationConnection connection,
            IList<Guid> recordIds)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetAuthorizedRecords", 1);

            StringBuilder parameters = new StringBuilder(128);
            foreach (Guid id in recordIds)
            {
                parameters.Append(
                    "<id>" + id.ToString() + "</id>");
            }
            request.Parameters = parameters.ToString();

            request.Execute();

            Collection<HealthRecordInfo> results =
                new Collection<HealthRecordInfo>();

            XPathNodeIterator records =
                request.Response.InfoNavigator.Select(
                    GetRecordXPathExpression(request.Response.InfoNavigator));

            foreach (XPathNavigator recordNav in records)
            {
                results.Add(HealthRecordInfo.CreateFromXml(connection, recordNav));
            }
            return results;
        }
        /// <summary>
        /// Gets valid group memberships for a record.
        /// </summary>
        /// 
        /// <remarks>
        /// Group membership thing types allow an application to signify that the
        /// record belongs to an application defined group.  A record in the group may be 
        /// eligible for special programs offered by other applications, for example.  
        /// Applications then need a away to query for valid group memberships.
        /// <br/>
        /// Valid group memberships are those memberships which are not expired, and whose
        /// last updating application is authorized by the the last updating person to 
        /// read and delete the membership.
        /// </remarks>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        /// 
        /// <param name="applicationIds">
        /// A collection of unique application identifiers for which to 
        /// search for group memberships.  For a null or empty application identifier 
        /// list, return all valid group memberships for the record.  Otherwise, 
        /// return only those group memberships last updated by one of the 
        /// supplied application identifiers.
        /// </param>
        /// 
        /// <returns>
        /// A List of HealthRecordItems representing the valid group memberships.
        /// </returns>
        /// <exception cref="HealthServiceException">
        /// If an error occurs while contacting the HealthVault service.
        /// </exception>
        public virtual Collection<HealthRecordItem> GetValidGroupMembership(
            ApplicationConnection connection,
            HealthRecordAccessor accessor,
            IList<Guid> applicationIds)
        {
            StringBuilder parameters = new StringBuilder(128);
            if (applicationIds != null)
            {
                XmlWriterSettings settings = SDKHelper.XmlUnicodeWriterSettings;
                XmlWriter writer = null;
                try
                {
                    writer = XmlWriter.Create(parameters, settings);
                    for (int i = 0; i < applicationIds.Count; i++)
                    {
                        writer.WriteElementString(
                            "application-id",
                            applicationIds[i].ToString());
                    }
                }
                finally
                {
                    if (writer != null)
                    {
                        writer.Flush();
                        writer.Close();
                    }
                    writer = null;
                }
            }

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetValidGroupMembership", 1, accessor);

            request.Parameters = parameters.ToString();
            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "GetValidGroupMembership");

            XPathNavigator infoNav =
                request.Response.InfoNavigator.SelectSingleNode(infoPath);

            Collection<HealthRecordItem> memberships = new Collection<HealthRecordItem>();

            XPathNodeIterator membershipIterator = infoNav.Select("thing");
            if (membershipIterator != null)
            {
                foreach (XPathNavigator membershipNav in membershipIterator)
                {
                    memberships.Add(ItemTypeManager.DeserializeItem(membershipNav.OuterXml));
                }
            }

            return memberships;
        }
        /// <summary>
        /// Gets the permissions which the authenticated person 
        /// has when using the calling application for the specified item types 
        /// in this health record.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        /// 
        /// <param name="healthRecordItemTypeIds">
        /// A collection of uniqueidentifiers to identify the health record  
        /// item types, for which the permissions are being queried. 
        /// </param>
        /// 
        /// <returns>
        /// A list of <see cref="HealthRecordItemTypePermission"/> 
        /// objects which represent the permissions that the current
        /// authenticated person has for the HealthRecordItemTypes specified
        /// in the current health record when using the current application.
        /// </returns>
        /// 
        /// <remarks> 
        /// If the list of health record item types is empty, an empty list is 
        /// returned. If for a health record item type, the person has 
        /// neither online access nor offline access permissions, 
        /// HealthRecordItemTypePermission object is not returned for that
        /// health record item type. 
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="healthRecordItemTypeIds"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If there is an exception during executing the request to HealthVault. 
        /// </exception>
        /// 
        public virtual Collection<HealthRecordItemTypePermission> QueryPermissions(
            ApplicationConnection connection,
            HealthRecordAccessor accessor,
            IList<Guid> healthRecordItemTypeIds)
        {
            Validator.ThrowIfArgumentNull(healthRecordItemTypeIds, "healthRecordItemTypeIds", "CtorhealthRecordItemTypeIdsArgumentNull");

            Collection<HealthRecordItemTypePermission> permissions =
                new Collection<HealthRecordItemTypePermission>();

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "QueryPermissions", 1, accessor);

            request.Parameters =
                GetQueryPermissionsParametersXml(healthRecordItemTypeIds);

            request.Execute();

            XPathNavigator infoNav =
                request.Response.InfoNavigator.SelectSingleNode(
                    GetQueryPermissionsInfoXPathExpression(
                        request.Response.InfoNavigator));

            XPathNodeIterator thingTypePermissionsNodes =
                infoNav.Select("thing-type-permission");

            foreach (XPathNavigator nav in thingTypePermissionsNodes)
            {
                HealthRecordItemTypePermission thingTypePermissions =
                    HealthRecordItemTypePermission.CreateFromXml(nav);
                permissions.Add(thingTypePermissions);
            }
            return permissions;
        }
        private static HealthServiceRequest CreateGetUpdateRecordsForApplicationRequest(
            HealthServiceConnection connection,
            DateTime? updateDate)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetUpdatedRecordsForApplication", 1);

            StringBuilder parameters = new StringBuilder();

            if (updateDate != null)
            {
                parameters.Append("<update-date>");
                parameters.Append(SDKHelper.XmlFromDateTime(updateDate.Value));
                parameters.Append("</update-date>");
            }

            request.Parameters = parameters.ToString();

            return request;
        }
        internal static Collection<PersonInfo> GetAuthorizedPeople(
            ApplicationConnection connection,
            Guid personIdCursor,
            DateTime authCreatedSinceDate,
            Int32 numResults,
            out Boolean moreResults)
        {
            Validator.ThrowArgumentOutOfRangeIf(
                numResults < 0,
                "numResults",
                "GetAuthorizedPeopleNumResultsNegative");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetAuthorizedPeople", 1);
            StringBuilder requestParameters = new StringBuilder(256);
            XmlWriterSettings settings = SDKHelper.XmlUnicodeWriterSettings;
            settings.OmitXmlDeclaration = true;
            settings.ConformanceLevel = ConformanceLevel.Fragment;

            using (XmlWriter writer = XmlWriter.Create(requestParameters, settings))
            {
                writer.WriteStartElement("parameters");

                if (personIdCursor != Guid.Empty)
                {
                    writer.WriteElementString("person-id-cursor", personIdCursor.ToString());
                }

                if (authCreatedSinceDate != DateTime.MinValue)
                {
                    writer.WriteElementString(
                        "authorizations-created-since",
                        SDKHelper.XmlFromDateTime(authCreatedSinceDate));
                }

                if (numResults != 0)
                {
                    writer.WriteElementString("num-results", numResults.ToString(CultureInfo.InvariantCulture));
                }

                writer.WriteEndElement(); // parameters
                writer.Flush();
            }
            request.Parameters = requestParameters.ToString();

            request.Execute();

            Collection<PersonInfo> personInfos = new Collection<PersonInfo>();

            XPathExpression navExp =
                 SDKHelper.GetInfoXPathExpressionForMethod(
                     request.Response.InfoNavigator, "GetAuthorizedPeople");
            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(navExp);
            XPathNavigator nav = infoNav.SelectSingleNode("response-results/person-info");

            if (nav != null)
            {
                do
                {
                    PersonInfo personInfo = PersonInfo.CreateFromXml(connection, nav);
                    personInfos.Add(personInfo);

                } while (nav.MoveToNext("person-info", String.Empty));

                nav.MoveToNext();
            }
            else
            {
                nav = infoNav.SelectSingleNode("response-results/more-results");
            }

            moreResults = nav.ValueAsBoolean;

            return personInfos;
        }
        /// <summary>
        /// Generates a new signup code that should be passed to HealthVault Shell in order
        /// to create a new user account.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be application level. </param>
        ///
        /// <returns>
        /// A signup code that can be used to create an account.
        /// </returns>
        /// 
        public virtual string NewSignupCode(HealthServiceConnection connection)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "NewSignupCode", 1);
            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "NewSignupCode");

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath);
            return infoNav.SelectSingleNode("signup-code").Value;
        }
        /// <summary>
        /// Gets the application configuration information for the calling application.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be application level. </param>
        ///
        /// <param name="allLanguages">
        /// A boolean value indicating whether the localized values all languages should be 
        /// returned, just one language. This affects all properties which can have multiple 
        /// localized values, including <see cref="ApplicationInfo.CultureSpecificNames"/>, 
        /// <see cref="ApplicationInfo.CultureSpecificDescriptions"/>,
        /// <see cref="ApplicationInfo.CultureSpecificAuthorizationReasons"/>, 
        /// <see cref="ApplicationInfo.LargeLogo"/>,
        /// <see cref="ApplicationInfo.SmallLogo"/>,
        /// <see cref="ApplicationInfo.PrivacyStatement"/>,
        /// <see cref="ApplicationInfo.TermsOfUse"/>,
        /// and <see cref="ApplicationInfo.DtcSuccessMessage"/>
        /// </param>
        /// 
        /// <returns>
        /// An ApplicationInfo object for the calling application.
        /// </returns>
        /// 
        /// <remarks>
        /// This method always calls the HealthVault service to get the latest 
        /// information. It returns installation configuration about the calling 
        /// application.
        /// </remarks>
        /// 
        /// <exception cref="HealthServiceException">
        /// The HealthVault service returns an error.
        /// </exception>
        /// 
        public virtual ApplicationInfo GetApplicationInfo(
            HealthServiceConnection connection,
            Boolean allLanguages)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetApplicationInfo", 2);

            if (allLanguages)
            {
                request.Parameters += "<all-languages>true</all-languages>";
            }

            request.Execute();

            XPathExpression xPathExpression = SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator, "GetApplicationInfo");

            XPathNavigator infoNav
                = request.Response.InfoNavigator
                    .SelectSingleNode(xPathExpression);

            XPathNavigator appInfoNav = infoNav.SelectSingleNode("application");

            ApplicationInfo appInfo = null;
            if (appInfoNav != null)
            {
                appInfo = ApplicationInfo.CreateFromInfoXml(appInfoNav);
            }

            return appInfo;
        }
        /// <summary>
        /// Releases the authorization of the application on the health record.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        /// 
        /// <exception cref="HealthServiceException">
        /// Errors during the authorization release.
        /// </exception>
        /// 
        /// <remarks>
        /// Once the application releases the authorization to the health record, 
        /// calling any methods of this <see cref="HealthRecordAccessor"/> will result 
        /// in a <see cref="HealthServiceAccessDeniedException"/>."
        /// </remarks>
        public virtual void RemoveApplicationAuthorization(
            ApplicationConnection connection,
            HealthRecordAccessor accessor)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "RemoveApplicationRecordAuthorization", 1, accessor);

            request.Execute();
        }
        /// <summary>
        /// Gets the application settings for the current application and
        /// person.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be authenticated. </param>
        ///
        /// <returns>
        /// The complete set application settings including the XML settings, selected record ID, etc.
        /// </returns>
        /// 
        public virtual ApplicationSettings GetApplicationSettings(HealthServiceConnection connection)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetApplicationSettings", 1);

            request.Execute();

            XPathExpression xPathExpression
                = GetPersonAppSettingsXPathExpression(
                            request.Response.InfoNavigator);

            XPathNavigator appSettingsNav
                = request.Response.InfoNavigator
                    .SelectSingleNode(xPathExpression);

            ApplicationSettings settings = null;
            if (appSettingsNav != null)
            {
                settings = new ApplicationSettings();
                settings.ParseXml(appSettingsNav);
            }

            return settings;
        }
        /// <summary>
        /// Gets information about an open query.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The <see cref="AuthenticatedConnection"/> instance used to
        /// get information about the open query.
        /// </param>
        /// 
        /// <param name="queryId">
        /// The unique identifier of the open query for which the information 
        /// will be retrieved.
        /// </param>
        /// 
        /// <exception cref="ArgumentException">
        /// The <paramref name="queryId"/> parameter is empty.
        /// </exception>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="connection"/> parameter is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// An error occurred when HealthVault processed the request.
        /// </exception>
        /// 
        public virtual OpenQuery GetInfoFromOpenQuery(
            AuthenticatedConnection connection,
            Guid queryId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "NewQueryNullService");

            Validator.ThrowArgumentExceptionIf(
                queryId == Guid.Empty,
                "queryId",
                "QueryIdInvalid");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetOpenQueryInfo", 1);

            request.Parameters = "<query-id>" + queryId.ToString() + "</query-id>";
            request.Execute();

            return
                CreateOpenQueryFromGetInfoResponse(
                    request.Response.InfoNavigator);
        }
        /// <summary>
        /// Gets the information about the person specified.
        /// </summary>
        /// 
        /// <param name="connection">The connection to use to perform the operation. This connection
        /// must be authenticated. </param>
        /// 
        /// <returns>
        /// Information about the person's HealthVault account.
        /// </returns>
        /// 
        /// <remarks>
        /// This method always calls the HealthVault service to get the latest 
        /// information. It is recommended that the calling application cache 
        /// the return value and only call this method again if it needs to 
        /// refresh the cache.
        /// </remarks>
        /// 
        /// <exception cref="HealthServiceException">
        /// The HealthVault service returns an error.
        /// </exception>
        /// 
        public virtual PersonInfo GetPersonInfo(ApplicationConnection connection)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetPersonInfo", 1);

            request.Execute();

            XPathExpression personPath =
                GetPersonXPathExpression(request.Response.InfoNavigator);

            XPathNavigator infoNav =
                request.Response.InfoNavigator.SelectSingleNode(personPath);

            return PersonInfo.CreateFromXml(connection, infoNav);
        }
        /// <summary>
        /// Creates a new open query using the specified 
        /// connection, definition, expiration time,
        /// personal identification number (PIN), description, and XSL.
        /// </summary>
        /// 
        /// <param name="connection">
        /// A <see cref="ApplicationConnection"/> instance that creates the 
        /// new open query.
        /// </param>
        /// 
        /// <param name="searcher">
        /// A <see cref="HealthRecordSearcher"/> instance that defines the open query.
        /// </param>
        ///
        /// <param name="expires">
        /// The number of minutes the query will expire from the creation time.
        /// A value of Int32.MaxValue denotes that the query does not expire.
        /// </param>
        ///
        /// <param name="pinCode">
        /// The PIN that protects the query.  
        /// </param>
        ///
        /// <param name="note">
        /// The note describing the query.
        /// </param>
        /// 
        /// <param name="finalXsl">
        /// The XSL that transforms the results of the query when the 
        /// <see cref="OpenQuery"/> is invoked.
        /// </param>
        /// 
        /// <returns>
        /// An <see cref="OpenQuery"/> instance that represents the newly created query.
        /// </returns>
        /// 
        /// <remarks>
        /// The creation of an open query makes public the data returned by that 
        /// query. However, the query URL must be known to retrieve the data.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="connection"/> or <paramref name="searcher"/> 
        /// parameter is <b>null</b>.
        /// </exception>
        /// 
        /// 
        /// <exception cref="ArgumentException">
        /// The <paramref name="searcher"/> parameter contains no valid search
        /// filters or the <paramref name="pinCode"/> parameter is <b>null</b> 
        /// or empty.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// An error occurred when HealthVault processed the request.
        /// </exception>
        /// 
        public virtual OpenQuery NewOpenQuery(
            ApplicationConnection connection,
            HealthRecordSearcher searcher,
            int expires,
            string pinCode,
            string note,
            string finalXsl)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "NewQueryNullService");
            Validator.ThrowIfArgumentNull(searcher, "searcher", "NewQueryNullSearcher");

            Validator.ThrowArgumentExceptionIf(
                searcher.Filters == null ||
                searcher.Filters.Count == 0,
                "searcher.Filters",
                "NewQuerySearcherNoFilters");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "SaveOpenQuery", 1, searcher.Record);

            request.Parameters =
                GetSaveOpenQueryParameters(
                    searcher,
                    expires,
                    pinCode,
                    note,
                    finalXsl);
            request.Execute();

            return
                CreateOpenQueryFromSaveOpenQueryResponse(
                    request.Response.InfoNavigator);
        }
        /// <summary>
        /// Allocates a package ID within HealthVault and returns it.
        /// </summary>
        /// 
        /// <remarks>
        /// <para>The package ID is allocated as a place holder for information that 
        /// is identifiable but not yet available through the HealthVault service.
        /// The returned package ID token should be stored or given to a patient, 
        /// then used in a call to CreateConnectPackage()
        /// to send the package data to the HealthVault service.</para>
        /// <para>The package ID is not a GUID.  It uses a shorter format that is more
        /// convenient for offline delivery and manual data entry.  The HealthVault 
        /// service guarantees that each package ID is unique for the lifetime of the 
        /// package.  Once the package has been accepted by the patient using the 
        /// HealthVault Shell, or explicitly deleted using the API, the package ID is 
        /// deallocated and may be reused.</para>
        /// </remarks>
        /// 
        /// <param name="connection">
        /// The HealthVault connection to use for the operation.
        /// </param>
        /// 
        /// <returns>
        /// A token that the application must give to the patient to use when validating the
        /// connection request.
        /// </returns>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        public virtual String AllocateConnectPackageId(
            OfflineWebApplicationConnection connection)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "AllocatePackageId", 1);

            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "AllocatePackageId");

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath);
            return infoNav.SelectSingleNode("identity-code").Value;
        }
        /// <summary>
        /// Removes the saved open query from the server.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection instance to use to remove the <see cref="OpenQuery"/>.
        /// </param>
        /// 
        /// <param name="id">
        /// The id of the open query to remove.
        /// </param>
        /// 
        /// <remarks>
        /// The person authenticated with the <paramref name="connection"/> 
        /// must have permission to remove the open query.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="connection"/> parameter is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// An error occurred when HealthVault processed the request.
        /// </exception>
        /// 
        public virtual void RemoveOpenQuery(
            ApplicationConnection connection,
            Guid id)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "NewQueryNullService");
            Validator.ThrowArgumentExceptionIf(
                id == Guid.Empty,
                "id",
                "QueryIdInvalid");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "DeleteOpenQuery", 1);

            request.Parameters = "<query-id>" + id.ToString() + "</query-id>";
            request.Execute();
        }
        /// <summary>
        /// Asks HealthVault to create a pending patient connection for the application specified
        /// by the connection with the specified user specific parameters.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to HealthVault. The application ID in the connection is used
        /// when making the patient connection.
        /// </param>
        /// 
        /// <param name="friendlyName">
        /// A friendly name for the patient connection which will be shown to the user when they
        /// go to HealthVault Shell to validate the connection.
        /// </param>
        /// 
        /// <param name="securityQuestion">
        /// A question (usually provided by the patient) to which the patient must provide the 
        /// answer when they go to validate the connection in the HealthVault Shell.
        /// </param>
        /// 
        /// <param name="securityAnswer">
        /// The answer to the <paramref name="securityQuestion"/> which the patient must use
        /// when validating the connection in HealthVault Shell. The answer is case-insensitive but
        /// otherwise must match exactly. In most cases it is recommended that this is a single 
        /// word to prevent entry problems when validating the connection.
        /// </param>
        /// 
        /// <param name="callbackUrl">
        /// Not yet implemented. May be null.
        /// </param>
        /// 
        /// <param name="applicationPatientId">
        /// The application specific identifier for the user. This identifier is used to uniquely
        /// identify the user in the application data storage whereas the HealthVault person ID is
        /// used to identify the person in HealthVault.
        /// </param>
        /// 
        /// <returns>
        /// A token that the application must give to the patient to use when validating the
        /// connection request.
        /// </returns>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// If <paramref name="friendlyName"/>, <paramref name="securityQuestion"/>,
        /// <paramref name="securityAnswer"/>, or <paramref name="applicationPatientId"/> is
        /// <b>null</b> or empty.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        /// 
        public virtual string CreatePatientConnection(
            OfflineWebApplicationConnection connection,
            string friendlyName,
            string securityQuestion,
            string securityAnswer,
            Uri callbackUrl,
            string applicationPatientId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");
            Validator.ThrowIfStringNullOrEmpty(friendlyName, "friendlyName");
            Validator.ThrowIfStringNullOrEmpty(securityQuestion, "securityQuestion");
            Validator.ThrowIfStringNullOrEmpty(securityAnswer, "securityAnswer");
            Validator.ThrowIfStringNullOrEmpty(applicationPatientId, "applicationPatientId");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "CreateConnectRequest", 1);

            request.Parameters =
                GetCreateConnectRequestParameters(
                    friendlyName,
                    securityQuestion,
                    securityAnswer,
                    callbackUrl,
                    applicationPatientId);

            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "CreateConnectRequest");

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath);
            return infoNav.SelectSingleNode("identity-code").Value;
        }
        /// <summary>
        /// Create authentication tokens and absence reasons for user 
        /// credentials, given the specified method, connection, and multiple 
        /// application ID's.
        /// </summary>
        /// 
        /// <remarks>
        /// The Shell primarily uses multiple application ID's when 
        /// constructing simple credential tokens: One each for the Shell and 
        /// for the target application.
        /// </remarks>
        /// 
        /// <param name="methodName">
        /// The HealthVault service method name to call.
        /// </param>
        /// 
        /// <param name="version">
        /// The version of the service method to call.
        /// </param>
        /// 
        /// <param name="connection">
        /// The <see cref="HealthServiceConnection"/> instance.
        /// </param>
        /// 
        /// <param name="applicationTokenCreationInfo">
        /// The application token creation information.
        /// </param>
        /// 
        /// <param name="stsOriginalUrl">
        /// The original url from the STS request.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="methodName"/>
        /// parameter is <b>null</b> or empty.
        /// </exception>
        /// 
        internal void MakeCreateTokenCall(
            string methodName,
            int version,
            HealthServiceConnection connection,
            ApplicationTokenCreationInfo applicationTokenCreationInfo,
            string stsOriginalUrl)
        {
            Validator.ThrowIfStringNullOrEmpty(methodName, "CreateTokenMethodNameIsNullOrEmpty");

            Validator.ThrowArgumentExceptionIf(
                applicationTokenCreationInfo == null,
                "appTokenCreationInfo",
                "AuthenticationAppIDCollectionNullOrEmpty");

            if (IsTokenCached(applicationTokenCreationInfo))
            {
                return;
            }

            AuthenticationMethodName = methodName;

            HealthServiceRequest request =
                new HealthServiceRequest(connection, AuthenticationMethodName, version);

            request.Parameters =
                ConstructCreateTokenInfoXml(applicationTokenCreationInfo, stsOriginalUrl);

            request.Execute();

            CreateAuthenticationTokenResult createAuthTokenResult =
                GetAuthTokenAndAbsenceReasons(
                    request.Response.InfoNavigator);

            ParseExtendedElements(request.Response.InfoNavigator);

            UpdateAuthenticationResults(createAuthTokenResult);
        }
        /// <summary>
        /// Gets the connections for the application that people have accepted since the specified
        /// date.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The application's connection to HealthVault.
        /// </param>
        /// 
        /// <param name="validatedSince">
        /// Connections that have been validated since this date will be returned. The date passed
        /// should be in UTC time.
        /// </param>
        /// 
        /// <returns>
        /// A collection of the connections that people have accepted.
        /// </returns>
        /// 
        /// <remarks>
        /// Validated connect requests are removed by HealthVault after 90 days. It is advised 
        /// that applications call <see cref="GetValidatedPatientConnections(Microsoft.Health.Web.OfflineWebApplicationConnection, DateTime)"/> 
        /// daily or weekly to ensure that all validated connect requests are retrieved.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        public virtual Collection<ValidatedPatientConnection> GetValidatedPatientConnections(
            OfflineWebApplicationConnection connection,
            DateTime validatedSince)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetAuthorizedConnectRequests", 1);

            if (validatedSince != DateTime.MinValue)
            {
                request.Parameters =
                    "<authorized-connect-requests-since>" +
                    SDKHelper.XmlFromDateTime(validatedSince) +
                    "</authorized-connect-requests-since>";
            }

            request.Execute();

            XPathExpression infoPath =
                SDKHelper.GetInfoXPathExpressionForMethod(
                    request.Response.InfoNavigator,
                    "GetAuthorizedConnectRequests");

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(infoPath);

            Collection<ValidatedPatientConnection> result =
                new Collection<ValidatedPatientConnection>();

            XPathNodeIterator validatedConnectionsIterator = infoNav.Select("connect-request");

            foreach (XPathNavigator nav in validatedConnectionsIterator)
            {
                ValidatedPatientConnection validatedConnection = new ValidatedPatientConnection();
                validatedConnection.ParseXml(nav);

                result.Add(validatedConnection);
            }
            return result;
        }
        /// <summary>
        /// Disassociates an alternate ID with a record.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        /// 
        /// <param name="alternateId">
        /// The alternate ID.
        /// </param>
        /// 
        /// <remarks>
        /// This method accesses the HealthVault service across the network.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The connection, accessor, or alternateId parameters are null.
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// The alternateId parameter is empty, all whitespace, or more than 255 characters in length.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// The HealthVault service returned an error. 
        /// If the alternate Id is not associated with a person and record id, the ErrorCode property
        /// will be set to AlternateIdNotFound.
        /// </exception>
        /// 
        public virtual void DisassociateAlternateId(
            ApplicationConnection connection,
            HealthRecordAccessor accessor,
            string alternateId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "AlternateIdConnectionNull");
            Validator.ThrowIfArgumentNull(accessor, "accessor", "AccessorNull");
            Validator.ThrowIfArgumentNull(alternateId, "alternateId", "AlternateIdNull");

            Validator.ThrowIfStringIsEmptyOrWhitespace(alternateId, "alternateId");
            Validator.ThrowArgumentExceptionIf(alternateId.Length > 255, "alternateId", "AlternateIdTooLong");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "DisassociateAlternateId", 1, accessor);

            request.Parameters = "<alternate-id>" + alternateId + "</alternate-id>";
            request.Execute();
        }
        /// <summary>
        /// Updates an existing pending patient connection with a new application patient identifier.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The HealthVault connection to use for the operation.
        /// </param>
        /// 
        /// <param name="oldApplicationPatientId">
        /// The application patient identifier that was used to make the initial connection request.
        /// </param>
        /// 
        /// <param name="newApplicationPatientId">
        /// The new application patient identifier.
        /// </param>
        /// 
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="connection"/> is <b>null</b>.
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// If <paramref name="oldApplicationPatientId"/> or <paramref name="newApplicationPatientId"/>
        /// is <b>null</b> or empty.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// If an error occurs when contacting HealthVault.
        /// </exception>
        /// 
        public virtual void UpdatePatientConnectionApplicationPatientId(
            OfflineWebApplicationConnection connection,
            string oldApplicationPatientId,
            string newApplicationPatientId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "ConnectPackageConnectionNull");
            Validator.ThrowIfStringNullOrEmpty(oldApplicationPatientId, "oldApplicationPatientId");
            Validator.ThrowIfStringNullOrEmpty(newApplicationPatientId, "newApplicationPatientId");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "UpdateExternalId", 1);

            request.Parameters = String.Join(
                String.Empty,
                new string[] {
                    "<old-external-id>",
                    oldApplicationPatientId,
                    "</old-external-id>",
                    "<new-external-id>",
                    newApplicationPatientId,
                    "</new-external-id>" });

            request.Execute();
        }
        /// <summary>
        /// Gets the list of alternate IDs that are associated with a record.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="accessor">
        /// The record to use.
        /// </param>
        /// 
        /// <remarks>
        /// This method accesses the HealthVault service across the network.
        /// </remarks>
        /// 
        /// <exception cref="HealthServiceException">
        /// The HealthVault service returned an error. 
        /// If the alternate Id is not associated with a person and record id, the ErrorCode property
        /// will be set to AlternateIdNotFound.
        /// </exception>
        /// 
        public virtual Collection<string> GetAlternateIds(
            ApplicationConnection connection,
            HealthRecordAccessor accessor)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetAlternateIds", 1, accessor);

            request.Execute();

            Collection<string> alternateIds = new Collection<string>();

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(
                        SDKHelper.GetInfoXPathExpressionForMethod(
                                request.Response.InfoNavigator,
                                "GetAlternateIds"));

            // Get the alternate ids that came back
            XPathNodeIterator alternateIdsNav = infoNav.Select("alternate-ids/alternate-id");

            foreach (XPathNavigator alternateIdNode in alternateIdsNav)
            {
                alternateIds.Add(alternateIdNode.Value);
            }

            return alternateIds;
        }
        /// <summary>
        /// Retrieves lists of vocabulary items for the specified 
        /// vocabularies and culture.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use for this operation. The connection
        /// must have application capability. 
        /// </param>
        /// 
        /// <param name="vocabularyKeys">
        /// A list of keys identifying the requested vocabularies.
        /// </param>
        /// 
        /// <param name="cultureIsFixed">
        /// HealthVault looks for the vocabulary items for the culture info
        /// specified using <see cref="HealthServiceConnection.Culture"/>.
        /// If <paramref name="cultureIsFixed"/> is set to <b>false</b> and if 
        /// items are not found for the specified culture, items for the 
        /// default fallback culture are returned. If 
        /// <paramref name="cultureIsFixed"/> is set to <b>true</b>, 
        /// fallback will not occur, and if items are not found for the 
        /// specified culture, empty strings are returned.
        /// </param>
        /// 
        /// <returns>
        /// The specified vocabularies and their items, or empty strings.
        /// </returns>
        /// 
        /// <exception cref="ArgumentException">
        /// The <paramref name="vocabularyKeys"/> list is empty.
        /// </exception>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="vocabularyKeys"/> list is <b>null</b> 
        /// or contains a <b>null</b> entry.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// There is an error in the server request.
        /// <br></br>
        /// -Or- 
        /// <br></br>
        /// One of the requested vocabularies is not found on the server.
        /// <br></br>
        /// -Or- 
        /// <br></br>
        /// One of the requested vocabularies does not contain representations 
        /// for its items for the specified culture when 
        /// <paramref name="cultureIsFixed"/> is <b>true</b>.
        /// <br></br>
        /// -Or- 
        /// <br></br>
        /// There is an error loading the vocabulary.
        /// </exception>
        /// 
        public virtual ReadOnlyCollection<Vocabulary> GetVocabulary(
            HealthServiceConnection connection, 
            IList<VocabularyKey> vocabularyKeys, 
            bool cultureIsFixed)
        {
            Validator.ThrowIfArgumentNull(vocabularyKeys, "vocabularyKeys", "VocabularyKeysNullOrEmpty");

            Validator.ThrowArgumentExceptionIf(
                vocabularyKeys.Count == 0,
                "vocabularyKeys",
                "VocabularyKeysNullOrEmpty");

            string methodName = "GetVocabulary";
            HealthServiceRequest request = new HealthServiceRequest(connection, methodName, 2);

            StringBuilder requestParameters = new StringBuilder(256);
            XmlWriterSettings settings = SDKHelper.XmlUnicodeWriterSettings;
            settings.OmitXmlDeclaration = true;
            settings.ConformanceLevel = ConformanceLevel.Fragment;

            using (XmlWriter writer = XmlWriter.Create(requestParameters, settings))
            {
                writer.WriteStartElement("vocabulary-parameters");

                for (int i = 0; i < vocabularyKeys.Count; i++)
                {
                    Validator.ThrowIfArgumentNull(vocabularyKeys[i], "vocabularyKeys[i]", "VocabularyKeysNullOrEmpty");

                    vocabularyKeys[i].WriteXml(writer);
                }

                writer.WriteElementString(
                    "fixed-culture",
                    SDKHelper.XmlFromBool(cultureIsFixed));

                writer.WriteEndElement(); //<vocabulary-parameters>
                writer.Flush();
            }
            request.Parameters = requestParameters.ToString();

            request.Execute();

            ReadOnlyCollection<Vocabulary> vocabularies
                = CreateVocabulariesFromResponse(methodName, request.Response);

            return vocabularies;
        }
        /// <summary>
        /// Gets the person and record IDs that were previosly associated
        /// with an alternate ID.
        /// </summary>
        /// 
        /// <param name="connection">
        /// The connection to use to access the data.
        /// </param>
        /// 
        /// <param name="alternateId">
        /// The alternate ID.
        /// </param>
        /// 
        /// <remarks>
        /// This method accesses the HealthVault service across the network.
        /// </remarks>
        /// 
        /// <exception cref="ArgumentNullException">
        /// The connection, accessor, or alternateId parameters are null
        /// </exception>
        /// 
        /// <exception cref="ArgumentException">
        /// The alternateId parameter is empty, all whitespace, or more than 255 characters in length.
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// The HealthVault service returned an error. 
        /// If the alternate Id is not associated with a person and record id, the ErrorCode property
        /// will be set to AlternateIdNotFound.
        /// </exception>
        /// 
        public virtual PersonInfo GetPersonAndRecordForAlternateId(
            ApplicationConnection connection,
            string alternateId)
        {
            Validator.ThrowIfArgumentNull(connection, "connection", "AlternateIdConnectionNull");
            Validator.ThrowIfArgumentNull(alternateId, "alternateId", "AlternateIdNull");

            Validator.ThrowIfStringIsEmptyOrWhitespace(alternateId, "alternateId");
            Validator.ThrowArgumentExceptionIf(alternateId.Length > 255, "alternateId", "AlternateIdTooLong");

            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetPersonAndRecordForAlternateId", 1);

            request.Parameters = "<alternate-id>" + alternateId + "</alternate-id>";

            request.Execute();

            XPathNavigator infoNav = request.Response.InfoNavigator.SelectSingleNode(
                        SDKHelper.GetInfoXPathExpressionForMethod(
                                request.Response.InfoNavigator,
                                "GetPersonAndRecordForAlternateId"));

            XPathNavigator personInfoNav = infoNav.SelectSingleNode("person-info");

            return PersonInfo.CreateFromXml(connection, personInfoNav);
        }
        /// <summary>
        /// Searches a specific vocabulary and retrieves the matching vocabulary items.
        /// </summary>
        /// 
        /// <remarks>
        /// This method does text search matching of display text and abbreviation text
        /// for the culture defined by the <see cref="HealthServiceConnection.Culture"/>. 
        /// The <paramref name="searchValue"/> is a string of characters in the specified 
        /// culture. 
        /// </remarks>
        /// 
        /// <param name="connection">
        /// The connection to use for this operation. The connection
        /// must have application capability. 
        /// </param>
        /// 
        /// <param name="vocabularyKey">
        /// The <see cref="VocabularyKey"/> defining the vocabulary to search. If the 
        /// family is not specified, the default HealthVault vocabulary family is used. 
        /// If the version is not specified, the most current version of the vocabulary 
        /// is used.
        /// </param>
        /// 
        /// <param name="searchValue">
        /// The search string to use.
        /// </param>
        /// 
        /// <param name="searchType">
        /// The type of search to perform.
        /// </param>
        /// 
        /// <param name="maxResults">
        /// The maximum number of results to return. If null, all matching results 
        /// are returned, up to a maximum number defined by the service config 
        /// value with key maxResultsPerVocabularyRetrieval.
        /// </param>
        /// 
        /// <param name="matchingVocabulary">
        /// A <see cref="VocabularyItemCollection"/> populated with entries matching 
        /// the search criteria.
        /// </param>
        /// 
        /// <param name="matchingKeys">
        /// A <b>ReadOnlyCollection</b> of <see cref="VocabularyKey"/> with entries
        /// matching the search criteria.
        /// </param>
        /// 
        /// <exception cref="ArgumentException">
        /// If <paramref name="vocabularyKey"/> is <b>null</b>.
        /// <br></br>
        /// -Or-
        /// <br></br>
        /// If <paramref name="searchValue"/> is <b>null</b> or empty or greater 
        /// than <b>255</b> characters.
        /// <br></br>
        /// -Or-
        /// <br></br>
        /// if <paramref name="searchType"/> is not a known 
        /// <see cref="VocabularySearchType"/> value.        
        /// <br></br>
        /// -Or-
        /// <br></br>
        /// when <paramref name="maxResults"/> is defined but has a value less than 1.        
        /// </exception>
        /// 
        /// <exception cref="HealthServiceException">
        /// There is an error in the server request.         
        /// <br></br>
        /// -Or-        
        /// <br></br>
        /// The requested vocabulary is not found on the server.
        /// <br></br>
        /// -Or- 
        /// The requested search culture is not supported. 
        /// </exception>        
        /// 
        public virtual void SearchVocabulary(
            HealthServiceConnection connection, 
            VocabularyKey vocabularyKey,
            string searchValue,
            VocabularySearchType searchType,
            int? maxResults,
            out VocabularyItemCollection matchingVocabulary,
            out ReadOnlyCollection<VocabularyKey> matchingKeys)
        {
            Validator.ThrowArgumentExceptionIf(
                String.IsNullOrEmpty(searchValue) || searchValue.Length > 255,
                "searchString",
                "VocabularySearchStringInvalid");

            Validator.ThrowArgumentExceptionIf(
                !Enum.IsDefined(typeof(VocabularySearchType), searchType),
                "searchType",
                "VocabularySearchTypeUnknown");

            Validator.ThrowArgumentExceptionIf(
                maxResults.HasValue && maxResults.Value < 1,
                "maxResults",
                "VocabularySearchMaxResultsInvalid");

            matchingVocabulary = null;
            matchingKeys = null;

            string methodName = "SearchVocabulary";
            HealthServiceRequest request = new HealthServiceRequest(connection, methodName, 1);
            StringBuilder requestParameters = new StringBuilder(256);
            XmlWriterSettings settings = SDKHelper.XmlUnicodeWriterSettings;
            settings.OmitXmlDeclaration = true;
            settings.ConformanceLevel = ConformanceLevel.Fragment;

            using (XmlWriter writer = XmlWriter.Create(requestParameters, settings))
            {
                if (vocabularyKey != null)
                {
                    vocabularyKey.WriteXml(writer);
                }

                writer.WriteStartElement("text-search-parameters");

                writer.WriteStartElement("search-string");
                writer.WriteAttributeString("search-mode", searchType.ToString());
                writer.WriteString(searchValue);
                writer.WriteEndElement(); // <search-string>

                if (maxResults.HasValue)
                {
                    writer.WriteElementString("max-results", maxResults.Value.ToString(CultureInfo.InvariantCulture));
                }

                writer.WriteEndElement(); //<text-search-parameters>
                writer.Flush();
            }
            request.Parameters = requestParameters.ToString();

            request.Execute();

            if (vocabularyKey != null)
            {
                matchingVocabulary = CreateVocabularyItemCollectionFromResponse(
                                        methodName, request.Response);
            }
            else
            {
                matchingKeys = CreateVocabularyKeysFromResponse(methodName, request.Response);
            }
        }
        /// <summary>
        /// Gets the request object including the necessary parameters for
        /// the "GetThings" request.
        /// </summary>
        /// 
        /// <returns>
        /// The request object for the thing search with the parameters filled
        /// in.
        /// </returns>
        /// 
        /// <exception cref="HealthServiceException">
        /// No filters have been specified.
        /// </exception>
        ///         
        private static HealthServiceRequest PrepareRequest(
            ApplicationConnection connection,
            HealthRecordAccessor accessor,
            HealthRecordSearcher searcher)
        {
            HealthServiceRequest request =
                new HealthServiceRequest(connection, "GetThings", 3, accessor);

            request.Parameters = GetParametersXml(searcher);
            return request;
        }