Understanding Personify Data Services Configuration

Authentication and Authorization

For security reasons, any request to available entities/service operations must be accompanied with authentication information (through Authentication Headers of Http Request), unless configured with "anonymous" access. For more information, please see Anonymous Data Services. The user name/password will be validated against PSM_USER configuration with respect to OrgId and OrgUnitId configured through "DefaultOrgId" and "DefaultOrgUnitId" entries in the web.config file. The entries would look like the following:

 

  <appSettings>

    <add key="DefaultOrgId" value="YourOrgId" />

    <add key="DefaultOrgUnitId" value="YourOrgUnitId" />

.

.

  </appSettings>

 

As of now, we do not support any authorization through Personify Data Services.

 

The authentication mechanism for Personify Data Services is developed using a custom ASP.NET Membership Provider (PersonifyMembershipProvider class in Personify.DataServices.Core.dll). The configuration for authentication (in web.config) would look like the following:

 

    <authentication mode="None">

      <!--<forms loginUrl="~/Account/Login.aspx" timeout="2880" />-->

    </authentication>

 

    <membership defaultProvider="PersonifyAuthProvider">

      <providers>

        <clear />

        <add name="PersonifyAuthProvider" type="Personify.DataServices.Core.Authentication.PersonifyMembershipProvider" />

      </providers>

    </membership>

 

The credentials for authentication will be accepted through "Basic Authentication" (at service level). Any request which does not carry authentication information will be changed dynamically using HTTP status code 401 (written using HttpModule). This is configured as follows:

 

  <system.webServer>

    <modules runAllManagedModulesForAllRequests="true">

      <add name="PersonifyBasicAuthenticationModule" type="Personify.DataServices.Core.Authentication.PersonifyAuthModule"/>

    </modules>

  </system.webServer>

 

As the "Basic Authentication" is dynamic, we can disable all authentication mechanisms for the service in IIS, as shown below:

Seat Information

Once the Personify360 Data Services is installed, you need to modify the web services’ config.xml file to match your portal settings.

To modify the config.xml file:

1.    Navigate to the Personify360 Data Services virtual folder you just installed.

2.    Open config.xml in a text editor, such as Notepad.

3.    Locate the following line in the file and enter the following values:

<Item Name="SeatInformation"

AssociationName=[YourAssociationName]

EnvironmentName=[YourEnvironmentName]

VersionName=[YourVersionName]

AppTypeName=[YourAppTypeName]

DatabaseName=[YourDatabaseName]

Login=[YourUserName]

Password=[YourPassword]/>

The "Login" value must be lowercase.

4.    Save and exit the file.

Session State and Persistence

Read/Write (RW) entities and service operations may maintain "state" across calls. For Read/Write entities, the service stores the TIMSS BusinessObject Collection directly as part of state. The developer has the flexibility to write to “state” when they are developing Service Operations.

 

The persistence of "state" is managed by a custom component developed using our own provider model. This component/provider (Personify.Persistence.AdoBocStateProvider) is completely different from that of ASP.NET session provider (and we do not use ASP.NET session in Personify Data Services).

 

Theoretically, we maintain sessions for all users accessing our service and this is managed automatically by our own session ID manager "PersonifySessionIDManager". This needs to be configured, as shown below:

    <sessionState

      cookieless="false"

      timeout="20"

      sessionIDManagerType="Personify.DataServices.Core.PersonifySessionIDManager, Personify.DataServices.Core"

      />

 

Behind the scenes, our persistence provider always works with SQL Server ASP.NET Session State tables (provided by Microsoft) to store the “state”. The persistence mechanism needs to be configured, as shown below:

  <configSections>

    <section name="PersonifyBocState" type="Personify.DataServices.Common.ConfigSection.Persistence.PersonifyPersistenceSection, Personify.DataServices.Common" />

  </configSections>

 

  <PersonifyBocState

    ProviderType="Personify.Persistence.AdoBocStateProvider"

    ConnectionString="Data Source=[YourServer];Initial Catalog=AspNetSqlSessionState;User Id=[YourUserId];Password=[YourPassword]"

    TimeOut="20"

    />

Layering and Customization

Personify360 Data Services is architectured in a way that can be easily customizable. Using the Web Services Designer, you can add new entities and service operations or modify existing entities. The Web Services Designer provides options to for default namespace or custom namespace. If you have opted to go with default namespace (“Use the default Namespace as shown below”), then there is no additional configuration required. If you have not opted to go with default namespace (“Use the Namespace provided below”), then it is required follow the steps below.

 

The layering configuration is usually carried through four sections and the default deployment comes with the configuration, as shown below:

  <configSections>

    <section name="PersonifyDataServicesLayer" type="Personify.DataServices.Common.ConfigSection.PersonifyDataAccessSection, Personify.DataServices.Common" />

  </configSections>

 

   <PersonifyDataServicesLayer Name="ServiceOperationLibraries">

    <LayerItem Priority="1" Name="Personify.DataServices.Business.Base" RootNamespace="Personify.DataServices.Business.Base" FileName="Personify.DataServices.Business.Base.dll" />

    <LayerItem Priority="2" Name="Personify.DataServices.Business.Generated.Base" RootNamespace="Personify.DataServices.Business.Generated.Base" FileName="Personify.DataServices.Business.Generated.Base.dll" />

  </PersonifyDataServicesLayer>

 

  <system.data>

    <DbProviderFactories>

      <add name="Personify EF Data Provider" invariant="PersonifyEFProvider" description="EF Provider for Personify" type="Personify.DataServices.EF.Provider.PersonifyProviderFactory, Personify.DataServices.EF.Provider, Version=1.0.0.0, Culture=neutral"/>     </DbProviderFactories>

  </system.data>

 

  <connectionStrings>

    <add name="PersonifyEntitiesBase" connectionString="provider=PersonifyEFProvider;metadata=res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.csdl|res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.msl|res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.ssdl;Provider Connection String='data source=XE;user id=edmuser;password=123456'" providerName="System.Data.EntityClient" />

  </connectionStrings>

 

If we add a new custom layer, the configuration changes for the above would look like the following:

 

<PersonifyDataServicesLayer Name="ServiceOperationLibraries">

    <LayerItem Priority="1" Name="Personify.DataServices.Business.Custom" RootNamespace="Personify.DataServices.Business.Custom" FileName="Personify.DataServices.Business.Custom.dll" />

    <LayerItem Priority="2" Name="Personify.DataServices.Business.Generated.Custom" RootNamespace="Personify.DataServices.Business.Generated.Custom" FileName="Personify.DataServices.Business.Generated.Custom.dll" />

 

    <LayerItem Priority="3" Name="Personify.DataServices.Business.Base" RootNamespace="Personify.DataServices.Business.Base" FileName="Personify.DataServices.Business.Base.dll" />

    <LayerItem Priority="4" Name="Personify.DataServices.Business.Generated.Base" RootNamespace="Personify.DataServices.Business.Generated.Base" FileName="Personify.DataServices.Business.Generated.Base.dll" />

 

  </PersonifyDataServicesLayer>

 

<connectionStrings>

    <add name="PersonifyEntitiesBase" connectionString="provider=PersonifyEFProvider;metadata=res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.csdl|res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.msl|res://Personify.DataServices.EF.Model.Base/Personify.DataServices.EF.Model.Base.DataModel.PersonifyDataModel.ssdl;Provider Connection String='data source=XE;user id=edmuser;password=123456'" providerName="System.Data.EntityClient" />

 

    <add name="PersonifyEntitiesCustom" connectionString="provider=PersonifyEFProvider;metadata=res://Personify.DataServices.EF.Model.Custom/Personify.DataServices.EF.Model.Custom.DataModel.PersonifyDataModel.csdl|res://Personify.DataServices.EF.Model.Custom/Personify.DataServices.EF.Model.Custom.DataModel.PersonifyDataModel.msl|res://Personify.DataServices.EF.Model.Custom/Personify.DataServices.EF.Model.Custom.DataModel.PersonifyDataModel.ssdl;Provider Connection String='data source=XE;user id=edmuser;password=123456'" providerName="System.Data.EntityClient" />

 

  </connectionStrings>

 

If the code for a class (or service operation) exists in more than one dll (mentioned in PersonifyDataServicesLayer element), only one is executed based on the priority set.

 

In the case of custom data service, if the data service layer name is "Customer", then in the web.config file of Personify Data Service, you need to replace the following highlighted below in yellow with the customer:

<system.serviceModel>

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

<services>

<service name="PersonifyDataServices.Customer.PersonifyDataCustomer">

<endpoint address="" binding="webHttpBinding" bindingConfiguration="higherMessageSize" contract="System.Data.Services.IRequestHandler" />

</service>

</services>

<bindings>

<webHttpBinding>

<binding name="higherMessageSize" maxBuggerSize="4194304" maxBufferPoolSize="4194304" maxReceivedMessageSize="4194304" transferMode="Streamed">

<readerQuotas maxDepth="32" maxStringContentLength="4194304" maxArrayLength="4194304" maxBytesPerRead="4096" maxNameTableCharCount="16384" />

</binding>

</webHttpBinding>

</bindings>

</system.serviceModel>

 

 

For example, for customer "APA", the service name would be:

<system.serviceModel>

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

<services>

<service name="PersonifyDataServices.APA.PersonifyDataAPA">

<endpoint address="" binding="webHttpBinding" bindingConfiguration="higherMessageSize" contract="System.Data.Services.IRequestHandler" />

</service>

</services>

<bindings>

<webHttpBinding>

<binding name="higherMessageSize" maxBuggerSize="4194304" maxBufferPoolSize="4194304" maxReceivedMessageSize="4194304" transferMode="Streamed">

<readerQuotas maxDepth="32" maxStringContentLength="4194304" maxArrayLength="4194304" maxBytesPerRead="4096" maxNameTableCharCount="16384" />

</binding>

</webHttpBinding>

</bindings>

</system.serviceModel>

The name of the service defined here MUST match the service in the svc (base: PersonifyData.svc)  file. If not, the system will NOT read the <webHttpBinding> configuration in the web.config file.

Additional Configuration

SSO Web.Config:

  <appSettings>

    <add key="svcUri" value="https://[ServerName]/PersonifyDataServices/PersonifyDataNSSWP.svc/"/>           

    <add key="EnableBasicAuthentication" value="true"/>

    <add key="TIMSSSearchCount" value="100" />

    <add key="SSO.ConnectionString" value="uid=[uuid];pwd=[pwd]; Initial Catalog=DBNAME;Data Source=ServerName”/>

    <add key="SSO.ProviderAssembly" value="System.Data" />

    <add key="SSO.ProviderType" value="System.Data.SqlClient.SqlConnection" />

    <add key="SSO.DatabaseType" value="SqlServer" />

    <add key="SSO.UseNamedParameters" value="true" />

  </appSettings>

 

Ebusiness Web.Config:

    <add key="svcUri" value="https://[ServerName]/PersonifyDataServices/PersonifyDataNSSWP.svc/"/>           

 

Registry Key entry:

“Username_NSSWP” = “[Username]

“Password_NSSWP” = “[Password]

 

Back office script:

UPDATE APP_INTERFACE_PARAMETER

SET PARAMETER_VALUE = ‘https://[ServerName]/PersonifyDataServices/PersonifyDataNSSWP.svc /'

WHERE INTERFACE = 'PERSONIFY_DATASERVICES'

AND PARAMETER_NAME = 'SERVICE_URL'

Managing Data Fetch

Personify Data Services need to be configured to determine how much  data can be retrieved per request (to eliminate unnecessary network traffic). 

  <appSettings>

    <add key="QueryWarningLimitLevel" value="1000"/>

    <add key="QueryErrorLimitLevel" value="1000"/>

    <add key="MaxRowsToFetchWithNoWherePredicate" value="100"/>

    <add key="EnableIncrementalDataLoad" value="False"/>

  </appSettings>

The configuration parameters used for this functionality  in the code above are:

·            QueryWarningLimitLevel: Query will execute and return the number of records as requested, but when logging is enabled, it will record to the log file that a query returned a result set that exceeded the number of records specified for the warning level.

·            QueryErrorLimitLevel: When the number of records to be returned by a query exceeds this value, an exception will be raised and the query will return no results.

·            MaxRowsToFetchWithNoWherePredicate: If a query is executed that does not have a where clause this is the maximum number of rows that will be returned by this query. This value is appended as a SELECT TOP (N) to the query

·            EnableIncrementalDataLoad: When this option is set to "True", the Personify APIs will perform a SELECT <Column Name List>, instead of a SELECT * request.