Wednesday, April 15, 2009

SharePoint Designer is FREE!

Yes.  It wasn’t an April fools joke as someone asked me :).  Microsoft actually made SharePoint Designer a free tool.  In case you don’t know about SharePoint Designer, it is the replacement product for FrontPage.  It’s a great tool that has all the capabilities of FrontPage, but clearly stands apart from that tool.  It’s meant to be a tool for power users and developers to modify pages within SharePoint sites.  It can be used to edit various HTML files in a stand-alone fashion, but SharePoint is really where it excels.

It’s a great thing that this tool is free.  You really can do a lot with it.  Enjoy:

http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=baa3ad86-bfc1-4bd4-9812-d9e710d44f42

Tuesday, April 14, 2009

Using CKS:EBE 2.5

I finally carved out some time to look into the latest updates to the CKS:EBE (Community Kit for SharePoint: Enhanced Blog Edition).  I took the dive, got the latest build and ran with it.  I’ve come to like it, but it wasn’t without a few issues.  I implemented EBE 2.0 about a year ago and always had some minor issues.  Things like CAPTCHA not working and a crazy amount of spam.  So I couldn’t receive comments.  I blogged a little but was mainly frustrated.  So I went to CodePlex to see what the great EBE team put together with the latest bits from (4/12/09).  Although there doesn’t appear to be too much in the way of updated news or documentation, I have to say the team really did a great job.  There were a number of improvements that fixed the issues I had with the previous version (2.0).

Having said that, the SharePoint blog site has some oddities that make it different than other sites.  And the CKS:EBE on top of that adds another layer of complexity.  With that complexity, I have to admit that it crossed my mind several times to just abandon this whole thing and start using my Live Spaces account.  But after some tweaking, things seem to be working fine now.

Things are still “under construction” but here’s a list of the items changed so far:

  • added the tag cloud to the “Intense” theme
  • removed links to trackbacks and trackback counters
  • removed anonymous permissions to the trackbacks received list –  I have no use for trackbacks.  I just want a simple blog :)
  • enabled alerts for comments so I’ll be notified when a comment comes in

These changes included changes to the files in the theme directory and the root directory using SharePoint Designer.

I’m hopeful that this package will meet my needs for blogging going forward.  Thanks EBE team.

Sunday, April 12, 2009

Sharing Resources among WSPs is Dangerous

Did you know that if you create two different SharePoint solution packages (WSPs) that both share assemblies or even images, that retracting the one of the solutions will remove the resource and break the other WSP(s)?

Let’s say you have a shared utility library that has some common SharePoint routines in it that gets installed in the GAC.  Ideally, you would want your clients to only install one solution package for this functionality.  So you build a workflow, for instance, that uses your utility assembly and install it and everything is OK.  The way you’d do that is to modify the manifest.xml so that the WSP includes your assembly, installs it into the GAC and makes the appropriate Safe Control entry, if necessary.  Your manifest.xml might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<Solution SolutionId="8d231d46-e165-4e39-8c69-dfd0d1b1d0de" ResetWebServer="True"
xmlns="http://schemas.microsoft.com/sharepoint/"
>
<!--Feature Manifest files-->
<
FeatureManifests
>
<
FeatureManifest Location="SuperWebPart\feature.xml"
/>
</
FeatureManifests
>
<!--Assembly files
-->
<
Assemblies
>
<
Assembly Location="SuperWebPart.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="SuperWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=de41bace3a102f2c"
Namespace="SuperWebPart" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
<
Assembly Location="MySuperUtilities.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="MySuperUtilities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf3856ad364e35"
Namespace="MySuperUtilities" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
</Assemblies
>
</
Solution>

You can see how the instructions above will place the utility library (MySuperUtilities.dll) in the GAC.


Next, you build another web part (or some other SharePoint thing: workflow, web page…) that needs to use the same utility library.  You also want clients to only have to install this one WSP.  It’s just simpler for them to have to install one WSP as opposed to multiple.  And this new web part may be installed on a farm that doesn’t have the first on installed.  So you, being a well-intentioned developer, make sure your manifest.xml includes the utility assembly.  Your second web part might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<!--
Manifest created STSDEV utility at 2/10/2009 1:37:08 PM
-->
<
Solution SolutionId="83224d36-a135-4bb9-cd39-dfdfddddfb23" ResetWebServer="True"
xmlns="http://schemas.microsoft.com/sharepoint/"
>
<!--
Feature Manifest files
-->
<
FeatureManifests
>
<
FeatureManifest Location="SuperDuperWebPart\feature.xml"
/>
</
FeatureManifests
>
<!--Assembly files
-->
<
Assemblies
>
<
Assembly Location="SuperDuperWebPart.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="SuperDuperWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b3adf5ce3a132f33"
Namespace="SuperDuperWebPart" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
<Assembly Location="MySuperUtilities.dll" DeploymentTarget="GlobalAssemblyCache"
>
<SafeControls>
<
SafeControl Assembly="MySuperUtilities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf3856ad364e35"
Namespace="MySuperUtilities" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
</Assemblies>
</
Solution>

So you can see how your two web parts will each install (and retract) the utility assembly (MySuperUtilities.dll).  Nice.  What happens when you want to install both web part packages on the same server.  No problem.  They both install and both work great.


Ok.  What’s the catch?  There’s always a catch :)  So the client decides that they don’t use the first web part.  They’ve decided to completely stop using it and want to retract the package using central admin or STSADM.  Unfortunately, as soon as they do that MySuperUtilities.dll is removed from the GAC, along with all the other files for this package.  Then the second web part will obviously break.



Note:


When talking about web parts and some other SharePoint coding concepts, you do have the option to use CAS (Code Access Security), which allows you to drop your DLLs in the /bin folder of your web application.  Using the bin avoids the complication of shared assemblies that may be removed.  The scenario that I’m describing here deals with a more common approach and that is adding assemblies in the GAC.  There’s a much larger discussion on CAS verses GAC, which I won’t go into here.


So how do we solve this dilemma?  Unfortunately, we have to install those shared resources manually or through a separate WSP.  I recommend a separate WSP, because it will assist you in deployment/retraction across an entire farm of servers.  So this WSP exists only to install DLLs or other shared resources.  This whole issue is a complex one to solve, but one I hope the SharePoint team addresses at some point.  It sure would be nice that before SharePoint retracted something in a farm, it would look at a complete list of farm resources in use by other packages to see if it can be retracted.  All that information is “known” by SharePoint in the configuration database anyway.  Then maybe it would prompt/warn users about these shared resources.

Saturday, March 21, 2009

Online Color Scheme Tool

If you have anything to do with user experience development, you often have to deal with colors.  For those of us programmers, it’s not something that comes naturally.  It seems more of an art than a science.  Actually, there’s quite a bit of science to it.  The human eye is attracted to color schemes that are based on mathematical formulas.  Some colors complement others better.  There are also a variety of tools that help you choose colors that “relate” to your main color choice.  I’ve used this approach on several projects and it’s worked quite well.

Here’s a very good tool from Petr Stanicek that allows you to choose a color and then look at different themes based on that color.  You can also download a dynamically generated CSS of your color choices.  A very cool application.  Kudos for Petr’s work and I urge you to donate so he can keep up this good work.

image_2_522C7B06.png (514×341)

Oh yeah, there’s no install.  It’s all through your browser:

http://colorschemedesigner.com/

Enjoy.

Sunday, December 28, 2008

Re-Provisioning Data in a SharePoint List

Synopsis: This post addresses a technique I recently found to provision data in a SharePoint list instance where a feature may be activated and deactivated.

The documentation here tells you how you can use the ListInstance element to provision an instance of a list and you can provision that list instance with rows of data.  Here's a simplified version of ListInstance XML I've used in a file:

<ListInstance
    Description="Contains all work locations."
    Id="Location"
    OnQuickLaunch="FALSE"
    TemplateType="10012"
    Title="Location"
    Url="Lists/Location">
    <Data>
        <Rows>
            <Row>
                <Field Name="Title">Jacksonville</Field>
            </Row>
            <Row>
                <Field Name="Title">Louisville</Field>
            </Row>
            <Row>
                <Field Name="Title">Marion</Field>
            </Row>
        </Rows>
    </Data>
</ListInstance>

What the documentation lacks is any explanation of what you can put in the Field attributes.  It's pretty intuitive that the Name attribute corresponds to the name of a field. It would have been nice if the documentation explained that this was the internal name, but that's ok.  Now we know, right?  Anyway, you can just specify any field available in your list structure.  Now, if we provision our feature the data will be provisioned to the designated list.  In the example above, I had created my own list (#10012), but this could be any out-of-the-box list or document library.

That's all good, but what happens if someone deactivates and re-activates the feature.  A very likely scenario.  In that case, data is duplicated each time.  The first time the feature is activated on an empty list the follow are created:

  • Jacksonville
  • Louisville
  • Marion

When the feature is deactivated and re-activated, the list instance provisioning process occurs again and the data is duplicated.  You end up with the following:

  • Jacksonville
  • Louisville
  • Marion
  • Jacksonville
  • Louisville
  • Marion

This was certainly not desirable behavior and was confusing to me why SharePoint would do this by default.  So my options had been to programmatically delete the list or empty the list during deactivation.  Not pretty in my opinion, but it got the job done.

I lived with this "problem" for many months until I got fed up and went on a hunt for the solution.  I spent time looking for a flag somewhere that would change this default behavior.  I looked for the longest time for a way to turn this off.  What I finally figured out is that by simply specifying the ID, I can control this.  The ID field is usually automatically generated for each item in the list.  Here we're able to set the value.  All I needed to do was to specify a unique value for the ID field for each row.  That's it!  So my resulting XML looked like this:

<ListInstance
    Description="Contains all work locations."
    Id="Location"
    OnQuickLaunch="FALSE"
    TemplateType="10012"
    Title="Location"
    Url="Lists/Location">
    <Data>
        <Rows>
            <Row>
                <Field Name="ID">1</Field>
                <Field Name="Title">Jacksonville</Field>
            </Row>
            <Row>
                <Field Name="ID">2</Field>
                <Field Name="Title">Louisville</Field>
            </Row>
            <Row>
                <Field Name="ID">3</Field>
                <Field Name="Title">Marion</Field>
            </Row>
        </Rows>
    </Data>
</ListInstance>

Now, when re-provisioning the list instance data, the three items I originally provisioned will never be duplicated like before.  I can deactivate/activate the feature to my heart's content.  This is helpful for simple lookup lists like states/provinces.

Tuesday, June 24, 2008

Fun with SharePoint Designer: Press Releases

Synopsis: This is one in a series of blogs on how I used SharePoint Designer in real-world solutions.  This covers creating a list and a set of pages in a WSS site that render press releases online.

I recently helped a client build a web site that required a press release page. On the main page, the anonymous users were supposed to see a list of short titles in the corner of the page.  When they click on that short title, they should be directed to a page that displays a full title and the full article.  Additionally, when users navigate to the tab on the top toolbar, they should see a listing of all the active press releases.  All this is to be styled using custom HTML defined in the master page.

From the administration perspective, we want the admin (not me as the programmer) to go into an admin area to edit these press releases.  They need to be able to create new ones, approve them and set begin/end dates on them.

A SharePoint list is a great solution to this.  The first big win is that we don't have to build much of the administration functionality at all.  With any SharePoint list, of course, you get all the input/listing and edit forms.  So the admin need only know how a list works.  Also, we want to be able to support things like versioning, check-in/check-out and lightweight approvals -- again, all available in a simple SharePoint list and all available in WSS as well as MOSS.  So we'll start in a simple blank site and build a custom list that meets our needs and call it "Press Releases."  From here, we'll add some columns to end up with these:

  • Title (already on the list, required)
  • ShortTitle (single line of text, required)
  • Body (multi-line text that supports rich text, required)
  • StartDate (date and time, required)
  • EndDate (date and time, required)

Your columns should look like this now:

image_2_01409BA9.png (559×219)

Then, while in List Settings, go to Versioning and enable that.  Also enable item approval, and check-in/check-out.  Approval is really all we need here, but the other is an added bonus for the administrator.  Add a couple of press releases to the list to have something like the following:

image_4_01409BA9.png (640×419)

The next thing we need to do is turn our attention to SharePoint Designer, as this will be the tool we'll use to render our data in various pages.  There are two pages we're concerned about: PressRelease.aspx, and ReleaseList.aspx.  The PressRelease.aspx page will show a single press release.  ReleaseList.aspx is going to show us multiple press release titles in a full-view page.  The default page could display a short list of press releases so users can see them right up front on our page. 

ReleaseList.aspx

Let's start with our most simple page, the ReleaseList page.  Using SharePoint Designer, create the ReleaseList.aspx page in the root of the site and, if you want, attach the master page so you have the look and feel you want to achieve.  In this exercise, we'll simply use a blank page so we don't make things too complicated.  You'll see something like this:

image_6_01409BA9.png (640×330)

Next we need to add some data from our list.  Go to the Task Panes menu and make sure the Data Source Library tab is selected.  If selected, you can see it appear to the right as an additional tab which is peer to the toolbox.  This task pane shows us all the data sources available in the environment.  When SharePoint Designer opens up, it communicates to the server to see what's available.  Notice you can have lists, document libraries, XML files, and external data.  Also, if you're using MOSS Enterprise, you'll see BDC data sources show up here.

Next, we need to select our data source (Press Releases list) and right-click to see a drop-down.  We'll choose Show Data, which will take us another task pane which shows us all the columns available in the list we've chosen.  Select the Press Releases list from the available lists and then choose to Show Data from the drop-down that appears, just like this:

image_10_01409BA9.png (622×480)

Once you do this, all the available columns show up in the display tab called Data Source Details.  From here, click the Title field and drag it to the design surface below the title.  This will render all the items in the list in design-time, which is pretty cool.  The resulting screen looks like this:

image_14_01409BA9.png (640×355)

Next we need to filter out those item which aren't approved and don't fall into the desired publishing timeframe.  Note, we'll use the Common Data View Tasks to do this.  Click on the filter link and then set the criteria as follows:

Approval Status = Approved

Start Date <= today

End Date >= today

The filter should look like:

image_18_01409BA9.png (438×258)

Next, you can adjust the layout by selecting the Data View Properties.

Now that we have a press release listing page, what happens when I click on a title?  Now, we need to link the title to the PressRelease page, which will display a single press release.  Select the Title and change it's type to Hyperlink as below.

image_12_01409BA9.png (640×355)

Continue through the warning about the trusted environment.  Change the following:

Address: PressRelease.aspx?id={@ID}

Text to Display: {@Title}

Your screen should look like this:

image_16_2F2DEE61.png (640×320)

PressRelease.aspx

Now, let's create PressRelease.aspx.  This page is going to receive a querystring parameter.  Let's start with another blank aspx page and choose the data library to find our Press Releases list first.  Then select "show data" to view the available columns.  Next, choose the Title and Body columns an choose to insert a single item view:

image_22_2F2DEE61.png (370×450)

Now, we need to filter the item that displays with the querystring parameter passed in.  Choose "Parameters" from the Common Data View Tasks pane that appears.  Then add a new parameter that looks at ID as a source parameter in the querystring.

image_24_2F2DEE61.png (502×333)

Next choose Filter from the Common Data View Tasks.  We need to filter the press releases to find the one from our newly created parameter.  The filter should look like this:

image_26_2F2DEE61.png (438×258)

Now you have a press release system.  Administrators can get to administrative pages to add/update press releases and end users can only see those press releases which are active and approved.  Through the use of a SharePoint list, we also have versioning, which is difficult to achieve in a typical database.

Monday, June 23, 2008

How to Provision a Link in Site Settings

Have you ever wondered how you could add your own links to the Site Settings area within SharePoint?  If you want to add a link that shows up in that location try this out.  The following is CAML provisioning code that is initiated by a feature.  This assumes you know what SharePoint Features are.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

    <CustomAction
       Id="MyCustomLink"
       GroupId="SiteCollectionAdmin"
       Location="Microsoft.SharePoint.SiteSettings"
       RequireSiteAdministrator="true"
       Sequence="300"
       Title="Synchronize Root Names">
        <UrlAction
           Url="_layouts/CustomApplicationPage.aspx" />
    </CustomAction>

</Elements>

This will give you a link as shown below:


Location tells SharePoint to target the site settings page.

GroupId tells SharePoint to put the link in the site collection administration section.

Sequence is the position in the list.  If you're not happy with it's position, just change the number.  Lower numbers appear higher in the list.

RequireSiteAdministrator is pretty self-explanitory.  If you're not a site administrator, you won't see the link.