August 2007 - Posts

As some of you know I have been doing quite a bit with MOSS Enterprise Search lately. I have got it working great for a lot of different things. As I was testing today, however I noticed when using the search box on the default search page, it was only returning exact matches of words. For example, I typed "enter" and did not get anything with the word "enterprise" in it. After some research, I remembered that the default search box uses a keyword search and keyword search does not support wildcards. This is extermely lame. I started looking for a solution and I stumbled upon Ontolica Wildcard Search.

Excited that someone might have already solved this problem for me, I immediately downloaded it and installed it. The automated setup errored out for me when trying to install one of the DLLs to the GAC (arg, don't use the GAC people). Since that didn't work, I manually installed the solution and deployed it and I was able to get it running.

It is effectively a new Search Center site with their own controls. When I got the new site created, I tried a wildcard search only to have it fail. It was not a product failure however, the wildcard search simply requires an asterisk (*) at the end of your string. I decided to see what configuration optons are available and have to say they have a very nice set of configuration pages. Everything is fully skinnable using XSLT. I was pleasantly surprised to find that there was an option to always apply the wildcard filter to your query.

One thing that is different is that it has its own search scopes. The scopes are actually configured via the search tabs. You have to go into Central Administration, edit the tab, and select the scopes there. The one thing that is different is that it has its own scopes and you have to map the MOSS scopes to the Ontolica scopes.

All in all I am pretty pleased with this product. I will guess that it saves me at least a week's worth of work trying to come up with my own solution to this problem. My biggest request for the company would be to properly apply code access security to their assemblies and put that in their solution file. I don't like the idea of a search page (that people like to try and hack anyway) running in full trust. I think this has got to be fixed because a lot of organizations will have an issue with it.

The best part of Onotolica Wildcard Search is that the product is free. They also offer a paid product, Ontolica Search that brings a lot of nice features to the table. It can search images, provides drill-down on results, and sort. All in all I am pretty impressed with the product. If you have a need to perform a wildcard search, this is definitely the way to go.

Ontolica Wildcard Search

This has been posted by a few others, but I wanted to make sure people knew about it. It is pretty simple to have Visual Studio create a WSP file for you every time you compile using MSBuild. Start by creating an XML file called Solution.build (or whatever). I typically put this in my Solution folder. This is going to simply execute the makecab.exe file with a path to your solution.ddf file (also typically in the Solution folder). It should look like this.

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="DesktopBuild" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="BuildSolutionPackage">
    <Exec Command="makecab.exe /F solution/cab.ddf"></Exec>
  </Target>
</Project>

The target name can be anything, just make a note of it because you will reference it when editing your .csproj file (your are using C# right?). This is the part that kind of sucks. Go edit your .csproj file with the text editor of your choice (i.e. notepad). Go to the end and look for the import statements and you'll see some post build type things commented out. That is where you want to paste the following.

<Import Project="Solution\Solution.build" />
<Target Name="AfterBuild">
  <CallTarget Targets="BuildSolutionPackage" />
</Target>

This is where the Target name has to match up. Once you do that, reload the project in Visual Studio. You'll get prompted for security or something because you customized the file. Just ignore it and move on. Now when you compile, it will make the .wsp file for you.

Eventually my goal is to figure out how to make some Team Build scripts for our MOSS solution. I think this is a step in the right direction. When I figure that out, I will post more on it. I also think there are some guidance packages out now that help with this but I have yet to find anything I really like yet. Maybe I will create my own someday.

Filed under: ,

I had promised an update to my Code Access Security post, so here it is. Hopefully, by now you have stopped being a cowboy and got your DLL out of the GAC and put the trust level back to minimal. If not, it is time. Here is some more info. Not just web parts require CAS. If you have any custom application pages or web user controls, more than likely they are going to require some CAS to work right. If anything the AspNetHostingPermission will be required for most things.

First I recommend, creating a SharePoint solution for everything (whether they are web parts or not). Follow the instructions in the last post to create a cab.ddf and Manifest.xml file. Put these in a folder called Solution (or whatever) in every single project you build. In my next post, I will explain how to add an msbuild target to create the wsp file everytime you compile.

I found that not all things were necessary in my last post but they do not hurt. Regarding lines like these in AssemblyInfo.cs.

assembly: AspNetHostingPermission(SecurityAction.RequestMinimum)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum,
Execution = true)]
[assembly: SharePointPermission(SecurityAction.RequestMinimum, ObjectModel = true, 
Impersonate = true, UnsafeSaveOnGet = true, Unrestricted=true)]

For the most part you can skip these. This just tells the assembly to not load if it hasn't already been granted permission to run. So if you dont want to add them, don't bother. However, you still do need AllowPartiallyTrustedCallers().

Sometimes when you set up a solution and you think everything is correct, your code still will give you permissions errors. Now I can tell you what installing the solution does behind the scenes so that you can check the system files and make sure everything made it in there correctly. First, it takes a copy of your web.config and makes a backup copy using a timestamp. It then modified the web.config to include any SafeControl elements you specified in the manfiest file. It also modifies the custom trust configuration file path. This is because it makes a copy of the minmal trust configuration file and makes a backup of it. You'll see a node entry similar to the following.

<trustlevel name="WSS_Custom" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server 
Extensions\12\config\wss_custom_wss_minimaltrust_5391d4d8-0991-4de1-b033-bc03de8f0bab.config" />

Be aware of this change when making changes to your web.config. Don't ever just overwrite it with whatever you have in source control because it will end up pointing to the wrong configuration file and none of your CAS will work any more.

If you examine the trust configuration file, you will find a permission set with the same name specified in your manifest file similar to the following (not necessarily the same permissions).

<PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for MyAssembly." Name="MyAssembly.wsp-eff41d49-7420-4f02-a884-e67752a447f0-1">
  <IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
  <IPermission class="SecurityPermission" version="1" 
Flags="Execution,ControlPrincipal,ControlAppDomain,ControlDomainPolicy,ControlEvidence" />
  <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, 
Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True"/>
  <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlThread, Execution" />
  <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="UserName" />
  <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089" version="1" Read="$AppDir$" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$" />
  <IPermission class="SqlClientPermission" version="1" Unrestricted="true" />
</PermissionSet>

You will also find a code group with the name of your permission set. Basically it is the name of your solution file plus some guid. This code group lists the path to your DLL.

<CodeGroup class="UnionCodeGroup" version="1" 
PermissionSetName="myassembly.wsp-eff41d49-7420-4f02-a884-e67752a447f0-1">
  <IMembershipCondition version="1" Name="MyAssembly" class="UrlMembershipCondition" Url="$AppDirUrl$/bin/MyAssembly.dll" />
</CodeGroup>

That is all that really happens behind the scenes when you install CAS via a WSP solution file. If you look in your conifguration file and you don't find your DLL listed in there, you know its not going to work. If the configuration looks good, double check the path in the web.config and make sure it is still loading the right configuration file. If not, a redeployment of all your solutions should fix it.

Just a quick tip today that may seem obvious after you have been working with MOSS Enteprise Search for a while. Start small. If you are going to be debugging a new entity, don't configure the BDC to load all the records of the table, stick a TOP clause in your SQL statement or stored procedure to limit the crawl. Crawling is really slow, working with 50 rows is a lot faster than waiting for it to index 50,000 (or millions for that matter). Once you think you have the right results being returned, schedule a crawl for after work and if you are lucky it might be done in the morning when you get back the next day.

Also another quick tip. If during the debugging process, the profile page of the SSP is not displaying the right data, reset IIS. Those profile pages get cached. In my case it was displaying a value of 1 for this new column I added for every single item indexed.

Yesterday, a new MOSS 2007 SDK was released and I am pretty excited about it for a number of reasons. First, the documentation is a bit more complete. Secondly, there is a new CHM included called MOSS 2007 Technical Articles and How-tos. This new CHM covers Excel Services more and also has videos on how to do various things in MOSS including the BDC and Enterprise Search. The thing that I like the most though is the new Business Data Catalog Definition Editor. Sorry BDC Meta Man, this looks like an end to your product.

This tool is pretty nice. It has a nice interface and can interact with anything you can pass a connection string to or a web service. It is really easy to add methods, however it does not create an Id enumerator out of the box (needed for Enterprise Search). Luckily that is easy to create. It can also use raw SQL or stored procedures. The nice thing I like about the tool is that it can Import existing XML files no matter how much I customize them. With BDC Meta Man, after I imported my custom security settings, it could not import the file any more.

The Business Data Catalog Definition Editor is installed seperately after you install the new MOSS SDK (be sure and uninstall the older one first). The installer can be found in Program Files\2007 Office System Developer Resources\Tools\BDC Definition Editor. For some reason the installation requires its own version of SQL Express (which it installs). The installation was pretty slow for some reason so be warned. I think it uses the database to persist state becuase when I launched the app again it had the same LOB system open.

If you do any BDC development (or MOSS development for that matter), I recommend you go download the new MOSS SDK today.

Office Server SDK