Saturday, August 1, 2009

Odd Error When Retrieving Items from an SPView

When attempting to retrieve items from an SPView programmatically, you cannot reference fields by name or by their ID.  Note, I’m using MOSS 2007 with SP2.  So here’s the code that causes the issue (and resulted in over 3 hours of wasted time)…

Guid listId = new Guid(...);
Guid viewId = new Guid(...);

SPList list = SPContext.Current.Web.Lists[listId];
SPView view = list.Views[viewId];

SPListItemCollection filteredItems = list.GetItems(view);

foreach (SPListItem item in filteredItems)
{
Response.Write(item["Title"]); // THIS FAILS
}

And you’ll see this error:


Exception has been thrown by the target of an invocation. ---> System.ArgumentException: Value does not fall within the expected range. at Microsoft.SharePoint.SPFieldMap.GetColumnNumber(String strFieldName) at Microsoft.SharePoint.SPListItemCollection.GetRawValue(String fieldname, Int32 iIndex) …


Thankfully, the SPView object exposes a Query property which is a string that contains the CAML that filters list items.  Using this property, you can just create your own SPQuery object and retrieve the items from the list.  The following code has this modification.


Guid listId = new Guid(...);
Guid viewId = new Guid(...);

SPList list = SPContext.Current.Web.Lists[listId];
SPView view = list.Views[viewId];

SPQuery query = new SPQuery();
query.Query = view.Query; // GET THE QUERY PROPERTY FROM THE VIEW

SPListItemCollection filteredItems = list.GetItems(query);

foreach (SPListItem item in filteredItems)
{
Response.Write(item["Title"]);
}

Hopefully, this saves you some time.

Tuesday, June 30, 2009

Document Library Icons Missing

Here’s something to keep in mind as you provision document libraries inside SharePoint.  You can provision document libraries through both the web (site) and site (site collection) scoped features.  The way you would do this is through use of the ListInstance element similar to the following:

<ListInstance
Id="Expenses" Title="Expenses" OnQuickLaunch="False" RootWebOnly="true"
FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101"
Description="Contains expense documents."
TemplateType="101" Url="Expenses">
</
ListInstance>

Unfortunately, when provisioning document library instances from site collection features the icons appear to be missing.  In the object model, which you can’t change after the fact, the ImageUrl property is empty.  If you look at the “View all site content” link, you’ll see what I’m talking about.


image_2_3B6F10A9.png (501×191)


This is just something to be aware of.  It may not be a show-stopper, but it’s an inconvenience to your users.  I’d recommend provisioning your lists as site features (at the Web scope).  It may mean more features to manage, however.

Thursday, June 11, 2009

Keep Site Definition IDs Unique

This recently bit me.  I had two different site definitions.  They had two different webtemp xml files, of course.

Here’s the first one:

<?xml version="1.0" encoding="utf-8" ?>

<Templates xmlns:ows="Microsoft SharePoint" >
  <Template Name="STORESITEDEF" ID="10010">

...

The second looked like this

<?xml version="1.0" encoding="utf-8" ?>

<Templates xmlns:ows="Microsoft SharePoint" >
  <Template Name="MARKETSITEDEF" ID="10010">

...

When I went to create my site, I kept getting this error:

The template you have chosen is invalid or cannot be found...

I incorrectly assumed that the ID was only relevant within a given site definition – why this wasn’t a GUID, I don’t know.  Anyway, I changed one of my IDs to be different and after an IISRESET all is well.

Tuesday, June 2, 2009

Always Capitalize (all-caps) Boolean Values in CAML

So here I was, late at night, banging my head against the desk trying to figure out why my a custom field’s custom property wasn’t hiding when I clearly stated Hidden=”true”.  As it turns out, you need to specify the uppercase value for that boolean or it simply won’t work.  There’s no error; it just doesn’t hide.  Here’s a snippet of code where this bit me while developing a custom column using the ProperySchema section to allow additional settings to be used for the field.

<FieldTypes>
<
FieldType>
<
Field Name="TypeName">CustomColumn</Field>
<
Field Name="ParentType">Note</Field>
<
Field Name="TypeDisplayName">My Custom Column</Field>
<
Field Name="TypeShortDescription">My Custom Column</Field>
<
Field Name="UserCreatable">TRUE</Field>
<
Field Name="ShowOnListCreate">TRUE</Field>
<
Field Name="ShowOnSurveyCreate">TRUE</Field>
<
Field Name="ShowOnDocumentLibraryCreate">TRUE</Field>
<
Field Name="ShowOnColumnTemplateCreate">FALSE</Field>
<
Field Name="FieldTypeClass">ACME.SharePoint.Blah.CustomField,
ACME.SharePoint.Columns, Version=1.0.0...</Field>
<PropertySchema>
<
Fields>
<
Field Name="MySetting"
Hidden="TRUE"
DisplayName="My Setting:"
MaxLength="500"
DisplaySize="40"
Type="Text">
<
Default></Default>
</
Field>
   ...

As you can see Hidden is set to “TRUE.”  “true” simply does not work.



What’s funny is that the WSS.XSD gives you intellisense in VS.NET (in most areas) for the following options for boolean fields: true, false, True, False, TRUE, FALSE.  Ok.  Why?


This was just one case where my choice of case caused an issue.  What about everywhere else?  So proceeded to tell my colleagues, including Bryan Phillips, about this oddity with hiding properties of custom fields.  He said that he always uses uppercase.  Not only for custom columns, but for everything.  I’ve typically used lowercase since it seemed to be close to my c# practices.  However, from now on, I’m going to capitalize my boolean values.

Wednesday, May 13, 2009

Understanding SharePoint Lists and Content Types

This post discusses lists and content types in SharePoint.  It’s an overview of the concepts from a developer’s perspective.

Before getting into content types, it’s important to do a brief review of Lists.  Central to SharePoint is the concept of a list, which is often compared to a database table.  If you spend any amount of time with lists you’ll quickly see the similarities.  Like database tables, lists have columns and rows.  You can query them, modify them, sort them and even index them.  And both lists and database tables also have a variety of column types for things like text, numbers, dates... Conceptually, they’re equals.

So why use lists in SharePoint?  Well, there are a number of features above and beyond what you can do with simple database tables.  Here are some of the main benefits:

  • User Interface: A SharePoint list provides not only the storage, but the user interface for working with the data.
  • Item Security: Lists support row-level security and security trimming.
  • Versioning: You can store multiple versions of data.
  • Ease of Use: Lists can easily be modified from within the browser.  End users can make these changes without a developer.
  • Content Types: Lists support content types.
  • There’s more, but I don’t have all day :)

User Interface

When you create a list in SharePoint, you get (for free) the user interface for working with the data in the list.  You get a new form, edit form, display form and a variety of views to display the data in a listing format.  As you add new columns the user interface changes and users can easily enter that information.  Compare this to a database table.  If you’re an end-user, you need to call a developer to modify the forms as fields change in the database.  A real pain and definitely not worth anyone’s time, in my opinion.

Item Security

You can lock down one row of data in a SharePoint list.  This not only prevents access to that one item, but it also prevents unauthorized users from actually seeing data in the list.  Even when you query the object model and retrieve items (rows) from a list, your results have unauthorized records trimmed out automatically.  That’s really cool.  Try doing that in a database.  It’s a lot more work.

Versioning

When you modify data in a SharePoint list, you have the option to enable versioning.  This will keep track of all changes for all columns in the list.  This feature also allows you to revert back to previous versions.  This is difficult to achieve in a database table solution.

Ease of Use

End users no longer have to bother the developer when they want to create a list to store something.  On their own, and with proper permissions, users can create and modify new lists.  Since all the forms are already done and up to date, users can essentially build a “web application” that has the functionality that used to take weeks to do in plain-old ASP.NET.  What?!!!  You mean that I can no longer charge my clients to build tables and the simple CRUD forms used to input/edit data?  That’s right.  All the out-of-the-box capabilities of SharePoint has essentially raised the bar regarding client expectations.  Clients expect it done now and can they actually do it themselves.  However ... do not despair.  There’s still plenty of software development to be done for your SharePoint users: workflows, web parts, custom jobs, custom forms...  Clients are never satisfied for long and, for a developer, this is a good thing.

Content Types

Let’s spend the remainder of this post on Content Types.  A content type is essentially a set of columns that can be used over and over in multiple lists.

Before we get too deep, you need to understand that columns can live on their own.  In a SharePoint site, there’s a special list of “Site Columns” that are already created and can be used in multiple lists.  For instance, there are standard columns like Author, Address, Spouse, and many more.  These are listed in the Site Column Gallery.  This is found on the Site Settings screen.

image_10_2D47FEB8.png (155×175)

And when you look at the Site Column Gallery, you’ll see a list of columns that Microsoft provides.  You can add your own, too.

image_8_2D47FEB8.png (529×409)

So Site Columns live in the Site Column Gallery.  They have all the settings required for each column.  For choices, these are things like the actual choices that need to be selected.  For others, it might be whether or not they’re required.

You can add one or more columns to a list when you go into the list settings screen of the list.  Here’s a simple Projects list where we want to add some site columns.  As you can see, it can be a real time-saver compared to creating new columns on the list each time.

image_12_2D47FEB8.png (514×264)

Next choose to add from existing site columns.

image_14_5B355170.png (640×259)

Then choose some columns to add.  Pretty easy.

image_16_5B355170.png (640×394)

So now we have a list with new columns no big deal.  But where do Content types come into this.  Well, just as we can add columns to a list, we can add columns to a Content Type.  Let’s create a Project content type and show how we can use that on two different lists (one for internal projects and one for external projects).

There’s another gallery that we need to introduce.  This is the Content Type Gallery.  Look under Site Settings and you’ll see this.

image_18_5B355170.png (170×182)

From here, we can see all of the built-in content types.  Open the Contacts content type and look around.

image_20_5B355170.png (640×451)

Notice how the Columns appear here just like they did in our list settings screen.  Although the content type doesn’t really store any data, it does define the structure of the data.  Let’s create a new content type for our projects.  Go back to the Content Type Gallery and click Create.

image_22_5B355170.png (285×111)

Next, give the content type a title and choose “Item” as the parent content type.  This is found under the “List Content Types” category.  I’ll talk more about the parent content type shortly. 

image_24_5B355170.png (640×395)

Once you’ve done this, you’ll be sent to the content type settings screen for your new content type.  From here, you can add new columns as necessary.  Notice that you already have a Title column.  This is because we chose the Item content type as it’s parent.  Item is the top-most content type for all items in SharePoint.  Every content type you create must use Item as a parent or some child of Item.  This is a really powerful concept that essentially lets you “inherit” the columns from a parent type.  It’s really just that simple.  We inherit from Item and we automatically get a Title fields.  If we inherited from Contact, we would get all the fields of Contact.  Let’s add some of our own fields for our project structure.

image_26_5B355170.png (279×165)

Note that you can create new site columns on the fly, but we’ll just choose from the existing site columns.  It’s quicker.  Add some columns that make sense for projects.

image_28_5B355170.png (503×280)

Now, let’s create a couple of custom lists: Internal Projects and Client Projects.  From the Create page, choose Custom List.

image_30_5B355170.png (172×157)

So now, we have three lists.  The one I originally started with where I added my own columns and the two we just created.  So we have two distinct lists to contain our internal and client projects now.  Let’s enable content types for each and then choose our “Project” content type.  Here are the steps for the Internal Projects list.  First, go to the settings for the list and choose Advanced Settings:

image_34_5B355170.png (578×333)

Next, choose to enable content types.

image_36_5B355170.png (640×72)

This gives us the ability to add new content types.  It also shows a new section in the list settings page that displays the content types that are in play.

image_38_5B355170.png (640×454)

Notice the new section.  Also notice that one content type is already in play.  Content types are always in play in SharePoint lists and document libraries.  Allowing management of content types simply let’s us see and work with them.

Next, add our Project content type.  Choose “Add from Existing Content Types” and choose project.

image_40_5B355170.png (640×314)

Save your changes and now, let’s see the list.  Click on the New button drop-down.

image_42_5B355170.png (306×165)

You can create new Item (that only has a Title) and a new Project that contains a new project form with all the fields we selected for our content type.  Here are the two forms.

image_44_5B355170.png (640×255)

So regardless of whether or not you’re in the Internal projects list or the Client Projects list, you’ll have the same form, but the data is stored in two different lists.  This concept doesn’t even exist in a typical database.  Try playing around with this.  Go back to one of your lists and chose a bunch of content types.  You’ll see some pretty impressive behavior:

image_46_4643CEFD.png (274×341)

Content types are quite powerful and I’ve just scratched the surface here.  They’re used all over the place in SharePoint.  In the MOSS Publishing and Collaboration Portal sites, content types are used to define the fields used in Page Layouts.  This is great concept that helps “prescribe” the fields that users can fill out in when creating new web pages for public facing sites.  And more at home, content types can be used with document libraries to define default document templates.  For instance, you can define a default “contract” document for your entire organization.  Then when users create new documents in a Document Library, they always have the latest contract boiler plate.

There’s certainly more to lists, document libraries and content types, but i hope this has given you a taste of the concept.  It took me a while to understand them, but I’m glad it finally sunk in.  Happy SharePointing.

Thursday, April 16, 2009

SharePoint Governance

We just had another great Kentucky SharePoint User Group meeting (KYSPUG) tonight.  Rob Bogue came all the way down from Indianapolis and spoke to the group about the topic of governance.  He did a wonderful job sharing with the group what governance is all about and how to get starting putting a plan in place so the business has a process to follow when it comes to SharePoint.  Here are some take-a-ways:

Quotas are a good thing.  A quota is a “governor” of sorts that can be set on SharePoint site collections which limits the overall content size.  Setting them relatively low helps keeps SLAs in-check because there are limits within SharePoint that can cause problems when exceeded.  For instance, you shouldn’t go beyond 100GB for a site collection’s size.  the size of the database becomes too unwieldy at that point when it comes to disaster/recovery scenarios, or even simple backup/restore scenarios for that matter.

In general governance is about the process, not so much a document.  However, when writing a document be very clear on what you mean.  Keep it concise.  Write just enough information and don’t fall into the trap of adding too much garbage that’s not really relevant. 

Getting “setup” properly, before you begin, is key.  If you don’t plan for things like training, you end up being in a reactionary state when you go to implement your governance plan/process.  Training is key, but often overlooked.  You don’t need to spend a lot of money however.  There are numerous reference materials online and plenty of books available.

Much thanks for Rob coming down to visit our group.

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.