Introducing the Cross Site Collection Search Configurator

While I was working at Intergen I was alerted to a small issue with configuring search keywords, best bets and synonyms. This simply being that they are set on a per site collection basis and there is no OOTB solution to share them. This has previously meant either using manual steps to ensure that your search settings are consistent across many site collections or the use of a product from Bamboo Solutions, sorry the name of the product escapes me at present, which is designed to do a whole lot more than just share search config.

Enter the Cross Site Collection Search Configurator a.k.a. CS2C. This solution is designed to allow you to share your site collection based search configuration between site collections in the same web application.

Currently the solution shares Keywords, Best Bets and Synonyms in a master and slave manner, that is using a new page in the Central Administration tool you set the Master Site Collection and then choose which site collections are to be slaves. This is coupled with a timer job which when activated against the web application runs hourly to synchronise all the Keywords, Best Bets and Synonym settings from the Master Site Collection to each of the Slave Site Collections.

Note: that currently if you manually set any Keywords etc. on a Slave Site Collection they will be lost when the timer job next runs.

This is definitely alpha software at this stage and although I’ve not found any bugs I’m sure they are lurking in there.

You can find the both the source code and a wsp over on CodePlex. Please be advised that this solution is built using Visual Studio 2008 and VSeWSS 1.2

At this stage my plans for future versions is to ensure that manual settings in Slave Site Collections are preserved, add support for sharing scopes across site collections and to improve the management screen.

Please do contact me if you have any feature requests, questions or comments.

Posted in Development, SharePoint, Tools | 2 Comments

Turn off custom error pages in SharePoint.

There are a number of good posts out there that will tell you how to get useful, for a developer, error messages out of SharePoint.

In addition to these great tips also ensure that you edit the web.config in your _layouts directory to disable custom error messages.

Posted in Best Practice, Development, SharePoint | Leave a comment

SharePoint and Agile

Go together like a horse and carriage.

Well, that’s my take anyway. I’ve been involved on a few SharePoint projects now that have taken a tradition approach, i.e. waterfall style, to the development of the customers desired end product. While we did deliver a good solution to the customer I feel that had we taken an agile approach then the end product delivered could have been an absolute killer!

So, why does SharePoint lend itself to an agile approach?

Users don’t get stuff until they see it. This holds true for all software, we’ve all drawn wire-frames and had whiteboard sessions to explain what this new application will look like. Then in the traditional space, the developer disappears into his darkened corner for days/weeks/months returning with something that resembles what was discussed. Oh sure it meets the requirements as they were stated in the requirements docs but does it work for the user? 

Rapid prototyping. When looking at SharePoint for document management or other intranet style usages it is simple to create a rough working model of what the client is after. This helps to ensure that the we can deliver what the client really wants, not just what we think they are asking for.

On the fly tweaks and changes. I was sitting in a demo session the other day with a client who was explaining how they would expect to interact with some data in a particular scenario. Now the views that I had over that calendar list didn’t help them to see what they needed to. Thanks to the ability to create custom views across lists and libraries I was able to whip up and fine tune a custom view. This view will help the users achieve their goals. I know that this view it right as it was essentially built by the user just with me manipulating the tools.

Users can build stuff themselves. Just taking the prototyping another step, users who have had some training can take on some of the prototyping themselves. Admittedly there’s not going to be huge numbers of users that will be able to or want to do this, however those that are this way inclined will love being able to get and involved.

Of course the usual arguments in favour of an agile methodology over a more traditional waterfall approach still hold. I refer you to the Agile Manifesto, Where is the Proof Agile Methods Work and Why Agile Software Development Techniques Work. Sure there are arguments against agile, but it is my firm belief that in the software services industry agile approaches will deliver the customer a solution that fits their needs better and reduce the cost of doing so.

Posted in Best Practice, Development | Leave a comment

SharePoint Bookmarklets

A workmate just put me onto a great resource that Zac showed during the Tech-Ed session on Tools and techniques which he presented with Matt.

These are a great set of bookmarks that work relative to your current page and let you quickly access various application pages, check out the SharePoint developer bookmarklets from Waldek Mastykarz.

Posted in SharePoint, Tools | Leave a comment

Sorting with a Comparison Delegate

I’ve just seen the awesome power of delegates, I can’t believe that I’ve never used them all that much before, mostly because I’ve been able to take advantage of using SQL or CAML to do my ordering, hey adding an ORDER BY or <OrderBy> clause is dead easy ;-).

Last night I was in the situation where I was composing a List<T> over n calls to the database and need to order my objects. Now in this case my business object have a few properties, actually they are WCF message objects, and I need to use a flexible ordering scheme as I know of at least two types of sort that are required at this stage. Enter delegate based sorting.

A quick look at the MSDN docs and I’m away.

Business Object:

 [DataContract]
 public class StudentSubmissionActivity
 {
     private string _courseCode;
     private string _description;
     private DateTime _dueDate;

     [DataMember]
     public DateTime DueDate
     {
         get { return _dueDate; }
         set { _dueDate = value; }
     }

     [DataMember]
     public string Description
     {
         get { return _description; }
         set { _description = value; }
     }

     [DataMember]
     public string CourseCode
     {
         get { return _courseCode; }
         set { _courseCode = value; }
     }
 }

CompareByDescription:

public static int CompareByDescription(StudentSubmissionActivity x, StudentSubmissionActivity y)
{
    if (null == x.Description)
    {
        if (null == y.Description)
        {
            // Both the same so return 0
            return 0;
        }
        //y.Description is non null therefore greater, return -1
        return -1;
    }
    else
    {
        if (null == y.Description)
        {
            // x.Description is non-null, therefore greater, return 1
            return 1;
        }
        // both are non-null do the comparison
        return x.Description.CompareTo(y.Description);

    }
}

As strings are nullable we need to do a bunch of null checking before we can call the native string.Compare method.

CompareByDueDate:

public static int CompareByDueDate(StudentSubmissionActivity x, StudentSubmissionActivity y)
{
    return x.DueDate.CompareTo(y.DueDate);
}

Here due to the fact that I’ve used standard DateTime objects I can skip the null checking and just use the native DateTime.Compare method straight off, however if I’d used the nullable DateTime? type then the null checking pattern used in the CompareByDescription method would be necessary.

Now using these comparison methods is dead easy!

Sample Usage:

public List<StudentSubmissionActivity> LoadSortedSubmissionActivities(List<string> courseCodes, StudentSubmissionActivitySorting sortOption)
{
    List<StudentSubmissionActivity> results = new List<StudentSubmissionActivity>();
    foreach (string courseCode in courseCodes)           
    {
                        DataAccess.StudentSubmissionActivity.LoadIntoListForCourse(results, courseCode);
    }

    if (StudentSubmissionActivitySorting.DateSort == sortOption)
    {
        results.Sort(CompareByDueDate);
    }
    else if (StudentSubmissionActivitySorting.DescriptionSort == sortOption)
    {
        results.Sort(CompareByDescription);
    }

    return results;
}
Posted in Development | Leave a comment