[Source: http://geekswithblogs.net/EltonStoneman]
The ASP.NET Web Part framework uses a plug-in framework for loading and saving personalization data to a persistent source. Out of the box, a SQL Server data source is provided (via the aspnet_regsql tool), along with a SQL personalization provider – specified in the system.web configuration section:
<webParts enableExport=“true“>
<personalization defaultProvider=“SqlPersonalizationProvider “>
<providers>
<add name=“SqlPersonalizationProvider”
type=“System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider”
connectionStringName=“local”
applicationName=“WcfPersonalizationSample“ />
It’s painless to set up and gets you running Web Part-enabled sites quickly. But if your Web servers and database servers are separated by a physical boundary with app servers in between, you can’t use the SQL provider directly from the ASP.NET application and will need to write a custom personalization provider.
Exposing the existing SQL personalization store through a custom WCF provider is a straightforward option – so your app server hosts a WCF service itself uses the SQL personalization provider, and the Web server uses the WCF service through the custom provider. Although the implementation is fairly trivial, there are a couple of issues to work around:
- PersonalizationProvider is an abstract class which requires you to implement methods with out and ref parameters. You’ll need to write methods with different signatures to work over WCF;
- SqlPersonalizationProvider has methods for loading personalization data as byte arrays, which are useful for the WCF service. To access them you’ll need another custom provider which inherits from SqlPersonalizationProvider, as the underlying methods are protected.
I’ve worked this through as a sample on MSDN Code Gallery: WCF Personalization Provider Sample.
To use it, the WCF service host needs to be configured to use the custom provider which wraps the SQL store, and a connection string entry for the data store:
<connectionStrings>
<add name=“local”
connectionString=“Data Source=.;Initial Catalog=WcfPersonalizationSample;Integrated Security=True”
providerName=“System.Data.SqlClient“ />
</connectionStrings>
<system.web>
<webParts enableExport=“true“>
<personalization defaultProvider=“PersonalizationServiceProvider“>
<providers>
<add name=“PersonalizationServiceProvider”
type=“WcfPersonalizationProvider.PersonalizationServiceProvider”
connectionStringName=“local”
applicationName=“WcfPersonalizationSample“ />
</providers>
</personalization>
</webParts>
…
(Note that this is using ASP.NET functionality in the WCF service, but you do not need to set the WCF service up for ASP.NET compatibility mode.)
The Web site need to be configured to use the custom provider which accesses the WCF service, and a service client entry for the WCF service:
<webParts enableExport=“true“>
<personalization defaultProvider=“WcfPersonalizationProvider“>
<providers>
<add name=“WcfPersonalizationProvider”
type=“WcfPersonalizationSample.ServiceClient.WcfPersonalizationProvider”
applicationName=“WcfPersonalizationSample“ />
</providers>
</personalization>
</webParts>
…
<client>
<endpoint address=“http://localhost/PersonalizationService.svc”
binding=“basicHttpBinding”
contract=“PersonalizationService.IPersonalizationService”
name=“BasicHttpBinding_IPersonalizationService“ />
</client>
And your Web Part personalization, for shared and user scopes, will work without the Web servers accessing the database.