Category Archives: Sharepoint

SharePoint base css

Here’s a simple stylesheet that I’m going to start using as a basis for customizing all of my Sharepoint team sites.

CleanCSS


/* Top Bar */
.ms-globalbreadcrumb
{
	background-color:#7caf72;
}

/* Header */
.ms-globalTitleArea
{
	background:none !important;
}

/* Navigation */
.ms-bannerContainer, .ms-pagemargin, .ms-navframe, .ms-leftareacell
{
	background:none !important;
}
.ms-nav
{
	background-image:none !important;
}
.ms-topnavContainer, .ms-topnavselected, .ms-topnav {
	border: none;
	background: none;

}

table.ms-topnavselected, table.ms-topnav {
	height: 30px;
	margin-left: 1px;
	margin-right: 1px;
}
.ms-topnavContainer div
{
	background-color:transparent !important;	
}
.ms-topNavFlyOuts, .ms-topNavFlyOuts a:link
{
	background-color:transparent !important;
}
/* Body */
body {
	text-align: center; 
	margin: 0px auto;
}
body.ms-BuilderBackground {
    text-align: left !important;}
.ms-main
{	
    background: #fff;  
    width: 1020px !important;
    height: 100%; 
    margin: 0px auto !important;	
    border-bottom:10px #7caf72 solid;
}
table.ms-main 
{
	text-align: left;
}
/* Gets rid of default light blue background everywhere */
.ms-pagemargin, .ms-nav, .ms-pagebottommargin, .ms-pagebottommarginleft, 
.ms-pagebottommarginright, td.ms-rightareacell div.ms-pagemargin, .ms-titlearealeft,
.ms-titlearearight, .ms-titleareaframe, .ms-pagetitleareaframe, 
.ms-pagetitleareaframe TABLE, .ms-bodyareapagemargin, .ms-bodyareaframe, 
.ms-areaseparatorright, .ms-areaseparatorleft
{
	background: transparent !important;
	border: none;
}

.ms-pagebreadcrumb a {
	background-color: transparent;
	color:#fff;
}

Configuring and Deploying Anonymous Publishing Sites for SharePoint Server 2007

Helpful article just posted:

http://msdn.microsoft.com/en-us/library/dd638968.aspx

Handy Regular Expressions

While working on a Sharepoint css file, I was able to use a nift regex instead of copying and pasting all over the place.

The tag I had looked like this:

#MSOZoneCell_WebPartWPQ4 td h3 a

I wanted to add a tag on the end so that it looked like this:

#MSOZoneCell_WebPartWPQ4 td h3 a, #MSOZoneCell_WebPartWPQ5 td h3 a

I used this Regex in Sharepoint Designer to do so:

Find

#MSOZoneCell_WebPartWPQ4 {.*$}

Replace

#MSOZoneCell_WebPartWPQ4 1, #MSOZoneCell_WebPartWPQ5 1

The “1” is called a “Tagged Expression”.  It refers to the part of the value that is tagged in the “Find” syntax.  You tag something using brackets, so in this case “.*$” was tagged, which corresponded to this part of the result ” td h3 a”.  I had about 10 of these, so this saved me a lot of time.

SharePoint Webpart Styling

I always wondered how to style a single webpart on the page.

http://www.heathersolomon.com/blog/articles/Controlling-Single-Web-Parts-with-CSS.aspx

Been dealing with CSS for a long time and never knew about attribute selectors.  Only issue is you can’t be in Quirks mode, which does mess up the rendering of some elements in SharePoint.

Sharepoint 2003 to 2007 Upgrade thoughts

I just completed a medium sized upgrade (83GB) for a client from Sharepoint 2003 to 2007 and thought I’d share a few things I took away from it:

  • You’re probably going to need to create a new Site Definition to map to the old one if the old one is customized at all
  • Set expectations with users upfront that while most of the things on the site will work correctly, there will be some issues (hopefully minor) that will have to be resolved post-upgrade.  For some reason, on the site I upgraded parts of the site were upgraded flawlessly while other parts had issues.
  • Perform the migration at least once in a dev environment and let users perform UAT.  Make sure you document their issues and how you fixed them.  This document proved invaluable once we did the production migration.
  • The database upgrade option is by far the safest and is recommended.

Some helpful links:

http://blogs.msdn.com/michael_yeager/archive/2007/08.aspx <– This was, by far, the most useful

http://blogs.msdn.com/sharepoint/archive/2007/03/06/how-to-upgrade-an-area-based-on-a-custom-site-definition.aspx

New Sharepoint Book

Here’s a new Sharepoint book that my manager Sean McDonough and John Ferringer co-wrote:

SharePoint 2007 Disaster Recovery Guide

Book Description:

Microsoft’s SharePoint technology gives organizations access to a wide range of tools and functionality designed to encourage collaboration, manage documents, discover shared knowledge, and much more. As the use of these resources through SharePoint grows, so does an organization’s dependency upon the availability and reliability of its SharePoint infrastructure. Disaster recovery is not a new concept in the realm of information technology nor is it unique to SharePoint, but as with any specialized technical platform, disaster recovery planning for SharePoint presents unique challenges and approaches. The problem is that SharePoint disaster recovery is not as simple as backing up your discs or load balancing your servers. It requires specialized activities to save data for recovery and to subsequently properly recover that same data. SharePoint professionals need a cohesive and comprehensive resource that guides them through the steps of planning, implementing, and testing the right disaster recovery plan for their situation. The “SharePoint 2007 Disaster Recovery Guide” provides such a resource. It provides a unique guidebook to all the necessary best practices, procedures, and tools for disaster recovery in SharePoint, such as how to plan for disaster recovery in SharePoint, and how to setup SharePoint, SQL Server, operating system, and file system backups step-by-step through SQL Server or STSADM.exe. The negative and positive aspects of every solution are detailed so that users can pick the disaster recovery plan that’s right for them. This is an essential guide for any IT professional tasked with protecting their organization’s valuable SharePoint data.

Amazon Link

Welcome Page Updater

During a recent uprade from Sharepoint 2003 to 2007, I noticed that some of the sites’ welcome pages weren’t getting set correctly. For some reason, they were set to UpgLandingPgRedir.aspx, which redirected to nowhere. Very convenient; must be a feature.

Here’s a piece of code I wrote that looks at every weclome page in your site collection and changes it if necessary. The Pause() isn’t necessary; I found it helpful to verify the changes that were being made.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;

namespace SPWelcomePageUpdater
{
    class SPWelcomePageUpdater
    {
        static void Main(string[] args)
        {
            Console.Write("Please enter the URL of the Sharepoint site: ");
            string url = Console.ReadLine();
            using (SPSite siteCollection = new SPSite(url))
            {
                SPWebCollection coll = siteCollection.AllWebs;

                for (int i = 0; i < coll.Count; i++)
                {
                    using (SPWeb targetWeb = coll[i])
                    {
                        SPList pagesLib = targetWeb.Lists["Pages"];
                        SPFile newWelcomePage = null;
                        foreach (SPListItem li in pagesLib.Items)
                        {
                            if (li.Name == "default.aspx")
                            {
                                newWelcomePage = li.File;
                            }
                        }

                        if (newWelcomePage != null)
                        {
                            if (PublishingWeb.IsPublishingWeb(targetWeb))
                            {
                                PublishingWeb publishingWeb = 
                                     PublishingWeb.GetPublishingWeb(targetWeb);
                                Console.WriteLine(publishingWeb.DefaultPage.Name);
                                if (publishingWeb.DefaultPage.Name=="UpgLandingPgRedir.aspx")
                                {
                                    // this sets the new welcome page
                                    publishingWeb.DefaultPage = newWelcomePage;    
                                    publishingWeb.Update();
                                    Console.WriteLine(publishingWeb.Name 
                                         + " welcome page updated.");
                                    Pause();
                                }
                                else if (!publishingWeb.DefaultPage.Url.ToUpper()
                                                .Contains("PAGES"))
                                {
                                    // this sets the new welcome page
                                    publishingWeb.DefaultPage = newWelcomePage;    
                                    publishingWeb.Update();
                                    Console.WriteLine(publishingWeb.Name 
                                         + " welcome page re-updated.");
                                    Pause();
                                }
                            }
                        }
                    }
                }
            }
        }
        static void Pause()
        {
            Console.WriteLine("Press any key to continue...");

            Console.ReadKey(true);
        }
    }
}

Infopath Item Level Security

Man it’s been awhile since I posted last.  Since nobody reads this, I guess it doesn’t matter.

Item level security on Infopath forms has been bugging me awhile.  It should be easy to set permissions for a form in the form library by using Rules or some other method.  However, that’s not the case.

You can do it using EventReceivers, though.  And I’m happy to say that it works pretty well.  Here’s the code:

public override void ItemAdded(SPItemEventProperties properties)
{
        Guid siteID, webID, listID;
        int itemID;
        SPUser curr;
        listID = properties.ListId;

        itemID = properties.ListItem.ID;
        using (SPWeb web = properties.OpenWeb())
        {
            siteID = web.Site.ID;
            webID = web.ID;
            curr = web.CurrentUser;
        }
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            using (SPSite site = new SPSite(siteID))
            {
                using (SPWeb web = site.OpenWeb(webID))
                {
                    SPList list = web.Lists[listID];

                    SPRoleAssignmentCollection roles = list.RoleAssignments;
                    SPListItem addedItem = list.GetItemById(itemID);
                    addedItem.BreakRoleInheritance(false);

                    SPRoleDefinition roleDefinition =
                    web.RoleDefinitions.GetByType(SPRoleType.Reader);

                    SPRoleAssignment roleAssignment =
                    new SPRoleAssignment(curr.LoginName.ToString(),
                    curr.Email.ToString(), curr.Name, "");

                    roleAssignment.RoleDefinitionBindings.Add(roleDefinition);

                    addedItem.RoleAssignments.Add(roleAssignment);

                    this.DisableEventFiring();

                    web.AllowUnsafeUpdates = true;
                    addedItem.Update();

                    this.EnableEventFiring();
                }
            }
        });

}

Sharepoint

I’ve been meaning to post my thoughts about my recent foray into Sharepoint for awhile now and since I finally have some time, here goes.

Development on Sharepoint sucks if you’re not doing it directly on the server.
-I can’t even count the number of hours I’ve spent copying a .cab file to the server, running stsadm.exe -o addwppack and restarting IIS.
Documentation for development on Sharepoint sucks.
-This was the first time I’ve ever developed against a platform with such limited documentation/examples. While it was pretty interesting, I would prefer to not do something like this again.

That being said, I thought I would post some of the code that I’ve written that may be useful. This first webpart allows you to search for users in the AD tree associated with your site:

        
private DataTable Search()
{
    SPSite siteCollRoot = new SPSite(SPContext.Current.Site.Url);
    DataTable dt = new DataTable();

    //must log in to the SSP and give the NT_AuthorityAuthenticated
    //users the Manage User Profiles and Personal site permissions
    //here (http://localhostssp/admin/_layouts/ManageServicePermissions.aspx)
    //in order for the code below to work
    //for all users
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {

        using (SPSite siteColl = new SPSite(siteCollRoot.ID))
        {
            ServerContext context = ServerContext.GetContext(siteColl);
            UserProfileManager upm = new UserProfileManager(context);
            UserProfile currentProfile;
            IEnumerator enumProfs = upm.GetEnumerator();
            bool continueEnum = true;

            DataColumn dc = new DataColumn("Title");
            dt.Columns.Add(dc);

            dc = new DataColumn("EMail");
            dt.Columns.Add(dc);

            dc = new DataColumn("JobTitle");
            dt.Columns.Add(dc);

            dc = new DataColumn("Department");
            dt.Columns.Add(dc);

            dc = new DataColumn("WorkPhone");
            dt.Columns.Add(dc);

            dc = new DataColumn("ID");
            dt.Columns.Add(dc);

            dc = new DataColumn("LastName");
            dt.Columns.Add(dc);

            dc = new DataColumn("FirstName");
            dt.Columns.Add(dc);

            while (continueEnum)
            {
                try
                {
                    continueEnum = enumProfs.MoveNext();
                }

                catch (Exception e)
                {
                    Console.WriteLine("EXCEPTION in enum: " + e.ToString());
                    continueEnum = enumProfs.MoveNext();
                }
                currentProfile = (UserProfile)enumProfs.Current;

                try
                {
                    DataRow dr = dt.NewRow();
                    dr["ID"] = currentProfile.ID.ToString();
                    dr["Title"] = currentProfile["PreferredName"].ToString();
                    dr["EMail"] = currentProfile["WorkEmail"].ToString();
                    dr["JobTitle"] = currentProfile["Title"].ToString();
                    dr["Department"] = currentProfile["Department"].ToString();
                    dr["WorkPhone"] = currentProfile["WorkPhone"].ToString();
                    dr["LastName"] = currentProfile["LastName"].ToString();
                    dr["FirstName"] = currentProfile["FirstName"].ToString();

                    dt.Rows.Add(dr);
                }
                catch (Exception ex)
                {

                }

            }

        }
    });

    return dt;
}

Switch to our mobile site