I've been doing a lot of digging around this topic this morning for my Search Explorer for Developers application (more on that in a future post).  In general it can be kind of tough to get search service applications and proxies when working without an HttpContext (like in a winforms app).  Even with context, it's not really a picnic connecting a proxy to a service application.  There may be better ways of doing this, and if/when I find them I'll happily update this post.  But for now, there are a few key concepts I wanted to cover in here for the OM developer that is trying to get at these service apps and proxies.

First, here's the code I am using to get all of the search service application proxies in the farm:

var apps = from SPServiceProxy ssp in theFarm.ServiceProxies

           from SPServiceApplicationProxy ssa in ssp.ApplicationProxies

           where ssa.GetType() == typeof(SearchServiceApplicationProxy)

           select ssa;

 

//enumerate results

foreach (SearchServiceApplicationProxy app in apps)

{

      //do something with the proxy here

}

There are a couple of things worth noting here.  First is the use of the double “from” statement in the LINQ query.  I’ve actually found this a pretty good way to dig into some of the collection members in LINQ.  Yes, I know there are other arguably “more elegant” ways to do this.  However, I am a simple human and as such I find this approach is easier to read, understand and develop than some of the more advanced LINQ techniques.  The other thing worth noting here is that this code does NOT retrieve a proxy for the FAST content service applications.  That’s because this special flavor of search service application does not have a proxy.  You will normally have two service applications for each implementation of FAST, but only one proxy.

Next, here’s some code to enumerate all of the search service applications in your farm.  It DOES include all of them, including both FAST content and FAST query:

SearchService s = new SearchService("OSearch14", SPFarm.Local);

foreach (SearchServiceApplication ssa in s.SearchApplications)

{

      //do something with the proxy here

}

One thing worth pointing out here is the method and string I used for creating the SearchService instance.  All I’ll say is that this is a method I stumbled upon in Reflector, and I can’t guarantee it will work / be supported at RTM time.  But it is working for now, and to date I haven’t found another non-deprecated method to achieve this same OM goodness.

Next on the list is getting the search service application associated with a specific search service proxy.  I won’t go into the backstory on this, but for now I will just say that this is the approach I’m least pleased with for now.  One day when I’m writing, er rambling, my memoirs I’ll explain why.  In the meantime this is a combination of some of the different methodologies described above:

//use a LINQ query to get the service app because using the Name doesn't

// work in the searchapplications collection

var srchApp = from SearchServiceApplication sapp in s.SearchApplications

              where sapp.Name == p.GetSearchApplicationName()

              select sapp;

 

SearchServiceApplication serviceApp = srchApp.First();

 

Nothing really to add there, I think that chunk of code is fairly straightforward.  Finally, if you do have an HttpContext it’s a lot easier to get the search service application proxy.  Here are a couple of examples of how you might do that:

//SPServiceContext spc = SPServiceContext.Current;

//OR

//SPServiceContext spc = SPServiceContext.GetContext(SPContext.Current.Site);

//OR

//SPServiceContext spc = SPServiceContext.GetContext(this.Page.Context);

//THEN

//SearchServiceApplicationProxy p =

//(SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(spc);

So there you go, lots of different ways of working with some common elements of search administration.