Examples of how services should get spweb url / connection strings?

Jun 26, 2011 at 3:52 PM

Can someone give me examples of how your services get config related information needed to access the underlying data? 

Right now I have these types of services:

  • Database - Pass ConnectionString to constructor
  • SPList - Pass SPWeb Url, ListName to constructor
  • SPSearch (KeywordQuery) - Pass Scope, QueryText to constuctor
  • Traditional WebServices - Pass values needed to create WebService

I'm very interesting in "refactoring" to use the SharePoint Service Locator.  I understand that my services will need empty constructors..  So I'm looking for examples to handle that.

I'm already using the IHierarchicalConfig for Application Settings..  Should I get an instance of that in each of my Services?

Any examples of what others are doing would be great!!

Jun 28, 2011 at 8:07 PM
Edited Jun 28, 2011 at 11:24 PM

Let's take your Database service as an example.
Suppose your database service MyDatabaseService implements interface IMyDatabase:

interface IMyDatabase
{
  string MyConnectionString { get; set; }
  //other interface members...
}

public class MyDatabaseService : IMyDatabase
{
  private string myConnectionString;
  public string MyConnectionString
  {
    get { return myConnectionString;}
    set { myConnectionString = value;}
  }
}

Here is what you can do to register MyDatabaseService to service locator and use your service in FeatureInstalled event handler

public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
  //register  MyDatabaseServie to service locator
  IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent();
  IServiceLocatorConfig typeMapping = serviceLocator.GetInstance<IServiceLocatorConfig>();
  typeMapping.RegisterTypeMapping< IMyDatabase, MyDatabaseService >();

  /*at this moment, the type mapping will be persisted at farm level property bag. From now on, whenever you call  serviceLocator.GetInstance< IMyDatabase >(), you will get an instance of MyDatabaseService. */

  //Retrive MyDatabaseService instance
  IMyDatabase myDatabaseServcie = serviceLocator.GetInstance< IMyDatabase >();
  myDatabaseServcie.MyConnectionString = "abcdefg";
}

Jun 28, 2011 at 10:49 PM

So this is setting the value after creating, I understand that part - but what I don't understand is how is that supposed to be persisted over what lifetime?  Several things will happen after the feature is installed..

 

Jun 28, 2011 at 11:31 PM
Edited Jun 28, 2011 at 11:40 PM

I added the following code comments at the code section above, and also fixed a typo.

/*at this moment, the type mapping will be persisted at farm level property bag. From now on, whenever you call serviceLocator.GetInstance< IMyDatabase >(), you will get an instance of MyDatabaseService. */

Since the type mapping is persisted when featrue is installed, you don't have to recreate typemapping everytime you need it unless you want to change the mapping. the following code shows how you call other method of IMyDatabase after feature is installed:

IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent();
IServiceLocatorConfig typeMapping = serviceLocator.GetInstance<IServiceLocatorConfig>();

/*the following code will give you a new instance of MyDatabaseService since it is mappped to IMyDatabase in the farm level property bag*/
IMyDatabase myDatabaseServcie = serviceLocator.GetInstance< IMyDatabase >();

myDatabaseServcie.OtherMethod();

 

 

Jun 29, 2011 at 12:52 PM

There is one line of code that can be eliminated in the above code - you only need to access service locator config when you are registering new services.  Therefore the access would look like:

IServiceLocator serviceLocator = SharePointServiceLocator.GetCurrent(); 
IMyDatabase myDatabaseService = serviceLocator.GetInstance< IMyDatabase >();
myDatabaseService.OtherMethod();
The default backing stores are farm, web app, and site collection property bag (farm and web app implement a custom SPPersistedObject for its store that's a child to the farm and web app property bags respectively.
There is also a sample for how to replace the underlying store in the download, where a list is used as a backing store instead of a property bag.
Jun 29, 2011 at 5:58 PM
Edited Jun 29, 2011 at 5:59 PM

connection string is not persisted. So everytime you get a new instance of MyDatabaseService, you will need to set the connectionsting.

Jun 29, 2011 at 6:35 PM

Hanz is correct, but there is another capability in the library that you can use.  I actually confused the two in my response. 

We also have a configuration manager (the service locator config is stored in the farm or site collection property bag using the configuration manager). 

You can store the connection string directly using the configuration manager.  You can get a reference to the configuration manager using the service locator at runtime.  This scenario is clearly documented in the msdn documentation.

There is no UI for configuration manager, you therefore need to either set the values programmatically, or you need to build your own. 

 

 

Jul 13, 2011 at 5:42 AM

I ended up basically using the IConfigManager to get all the required settings within the default constructor.  I didn't want to have to worry/think about setting properties after getting the service instance.

 

Thanks!