Deleting a Federated Location via the API
I’m working on a SharePoint feature which will automatically add a federated search location on feature activation and which will delete it on de-activation.
To accomplish this I use the Microsoft.Office.Server.Search.Administration.SearchServiceApplication class, and more specifically the AddNewLocationConfiguration and DeleteLocationConfiguration methods. I tried to use the same methods of the SearchServiceApplicationProxy first, but there seems to be an error using the AddNewLocationConfiguration method on proxy object.
AddNewLocationConfiguration takes a LocationConfiguration object as parameter, which can be created by loading in the xml from an OSDX file like this:
var searchLocation = new LocationConfiguration();
var stream = …stream to xml file…;
searchLocation.Import(stream);
As you see, adding is not too hard, but deleting is the problem. The DeleteLocationConfiguration method takes the id of a LocationConfiguration object as the parameter. But lo and behold, the Id property is defined as internal.
That means it’s not available for us to delete on. But we’re lucky to use .Net where reflection is possible. Buy using the helper class below we can get the value from the internal property. Note that the code could have used regular reflection, but emitting IL makes more optimized code, and I use this utility class a lot of other places where performance is an issue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span class="kwrd">public</span> <span class="kwrd">class</span> DynamicReflectionHelperforObject<V>{ <span class="kwrd">public</span> <span class="kwrd">delegate</span> T GetPropertyFieldDelegate<T>(V obj); <span class="kwrd">public</span> <span class="kwrd">static</span> GetPropertyFieldDelegate<C> GetP<C>(<span class="kwrd">string</span> memberName) { Type v = <span class="kwrd">typeof</span>(V); PropertyInfo pi = v.GetProperty(memberName, BindingFlags.NonPublic | BindingFlags.Instance); <span class="kwrd">if</span> (pi == <span class="kwrd">null</span>) <span class="kwrd">throw</span> <span class="kwrd">new</span> NullReferenceException(<span class="str">"No Property or Field"</span>); DynamicMethod dm = <span class="kwrd">new</span> DynamicMethod(<span class="str">"GetPropertyorField_"</span> + memberName, <span class="kwrd">typeof</span>(C), <span class="kwrd">new</span> Type[] { v }, v.Module); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); <span class="rem">// loaded c, c is the return value </span> il.EmitCall(OpCodes.Call, pi.GetGetMethod(<span class="kwrd">true</span>), <span class="kwrd">null</span>); il.Emit(OpCodes.Ret); <span class="kwrd">return</span> (GetPropertyFieldDelegate<C>)dm.CreateDelegate(<span class="kwrd">typeof</span>(GetPropertyFieldDelegate<C>)); } } |
1 2 3 4 |
<span class="kwrd">int</span> id = Helpers.DynamicReflectionHelperforObject<LocationConfiguration> .GetProperty<<span class="kwrd">int</span>>(<span class="str">"Id"</span>) .Invoke(frontLocation); fastQuerySSA.DeleteLocationConfiguration(id); |