Friday, August 21, 2009

Useful code for modifying a Site

I am currently working on a project that needs to support the clients SharePoint implementation. They do everything directly in production, so I have created a site definition to reproduce there site structure. One feature I created to help me with this is basically a web scoped feature that modifies the site with custom changes I want in code (I am a programmer after all!!).

The following code does some interesting stuff:
  • Creates a document library in code
  • Sets the document library title, enables versioning and allows content types in the document library
  • Finds a site content type and associates it with the document library
  • Changes the content type order so it contains just my content type
  • Sets the default page of the site to the default view of the document library
  • Adds some of my content type fields to the default view


public class ProjectSiteReceiver : SPFeatureReceiver
{
    private string _documentLibraryTitle = "Project Documents";
 
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        using (SPWeb web = (SPWeb)properties.Feature.Parent)
        {
            SPListTemplateType templateType = SPListTemplateType.DocumentLibrary;
            Guid listId = web.Lists.Add(_documentLibraryTitle, null, templateType);
 
            SPList list = web.Lists[listId];
            list.Title = _documentLibraryTitle;
            list.EnableVersioning = true;
            list.ContentTypesEnabled = true;
            list.Update();          
 
            SPContentType contentType = web.GetContentType("Project Document");
            SPContentType listContentType = list.ContentTypes.Add(contentType);
            listContentType.Update();
 
            List<SPContentType> contentTypeList = new List<SPContentType>();
            contentTypeList.Add(listContentType);
            list.RootFolder.UniqueContentTypeOrder = contentTypeList;
            list.RootFolder.Update();
 
            SPFolder webFolder = web.RootFolder;
            webFolder.WelcomePage = list.DefaultView.Url;
            webFolder.Update();
 
            SPView view = list.DefaultView;
            view.ViewFields.Add("Project ID");
            view.ViewFields.Add("Project Type");
            view.Update();
        }
    }
 
    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        using (SPWeb web = (SPWeb)properties.Feature.Parent)
        {
            SPList list = web.GetListByName(_documentLibraryTitle);
            list.Delete();
        }
    }
 
    public override void FeatureInstalled(SPFeatureReceiverProperties properties)
    {
    }
 
    public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
    {
    }
}




PS: Sorry GetContentType and GetListByName are my own custom extension methods. There isn't much to them really, just better error handling then using the default SharePoint API methods with square brackets.

PPS: You also need to set the welcome page back to the default in the FeatureDeactivating method:

SPFolder webFolder = web.RootFolder;
webFolder.WelcomePage = "default.aspx";
webFolder.Update();

Opening SPFile from full file URL

I had to implement a custom search to find documents matching certain criteria. I could easily find a document and retrieve its "Path" (full url). From this URL, I needed to get the associated SPFile object. This took longer then I thought it warranted.

Here is the solution:

string fileUrl = dt.Rows[0]["Path"].ToString();
 
using (SPSite site = new SPSite(fileUrl))
{
    using (SPWeb web = site.OpenWeb())
    {
        SPFile file = web.GetFile(fileUrl);
 
        if (!file.Exists)
            throw new ApplicationException("Could not find document");
 
        return file;
    }
}

Wednesday, August 12, 2009

Sharepoint Assembly Platform

I recently started a project which consisted of a set of assemblies deployed to the GAC. While integrating with a larger application, the assemblies build configuration were modified to build on x86 Platform (32-bit) explicitly. This was done believing that if they were built as 32-bit, both 32-bit and 64-bit applications could use them.

This worked fine in a 32-bit environment. However, when deploying to a 64-bit environment I was getting "file not found" errors. After some looking into the C:\windows\assembly\gac_msil directory on the server I noticed there where multiple directories there:

  • gac_msil
  • gac32
  • gac64


After some research I discovered that on a 64-bit server, assemblies built as:

Any CPU: go into the gac_msil directory and can be used by either 32-bit or 64-bit processes.

x86: go into the gac32 directory and can only seen and used by 32-bit processes.

x64: go into the gac64 directory and can only be seen and used by 64-bit processes.

My conclusion: leave the build configuration as "Any CPU" !!!!

Monday, August 10, 2009

Unable to move web part

I had an error with not being able to move webparts from in a page. Something like this:



After a bit of research I found the the problem was related to web part zones having a relative position in the CSS. See http://www.sharepointblogs.com/tmt/archive/2007/11/01/CSS-causes-JavaScript-error-while-moving-Web-Parts-in-edit-mode.aspx .

There are a few ways mooted online to fix this problem, but the best solution for me was to set the position of body css element to relative also:

body
{
    position:relative;
}

Problem solved...