Friday, February 29, 2008

Using dll.config for GAC in a SharePoint Web

When building custom SharePoint event handlers, the compiled dll is installed to the GAC and is referenced by Windows SharePoint Services.... but what if the assembly has custom attributes that require a config file? Let's say for example, that you want to store smtp information to send out emails on a list item change, and it varies from site to site. Where do you put it?

The answer is that it isn't any different than if the assembly was referenced inside of a web application's bin folder. The custom attributes should reside in the web.config file in the SharePoint site web root. If you aren't sure where the directory that is mapped to the Sharepoint Web resides, open up the IIS Manager, right-click your SharePoint Web folder, and select "Open". Now add your custom properties to this web.config file, save your changes and restart IIS. Don't forget to add the configSection for your custom application settings!

More Information:
MSDN:configSections Element (General Settings Schema)

Thursday, February 28, 2008

Spreadsheet Export Link Custom Column Type

Recently at a client there was a need to export multiple spreadsheets of a list, but each with a different filter. For one or two filters, the easy solution would be to create a different view for each filter of the list, navigate to that view and click on the "Export to Spreadsheet" option. When you go past four or more, it quickly becomes tedious, especially when these spreadsheets are meant to be as current as possible. My first solution to this was to add a Link Webpart to a page, and each link would export one of the views of the list. You can read about how to format the link a spreadsheet export link here. Although it was much easier for the user to generate these spreadsheets now that they were all in one place, it required a great deal of additional knowledge to maintain, in that the GUIDs for the view and the list need to be determined and added to the link.

So what next? Turns out, this is a perfect fit for a Custom Field Type! Specifically, an extended SPFieldMultiColumn. Why the Multi-column? We use the Multi-column so that the generated link will look nice and hide the user-scaring querystring in the spreadsheet url. For more in-depth coding and configuration of a custom field type read here.

Here's the code in vb (for all you out there that don't like the above referenced c# example)

Here is where the magic really happens:
Public Function GetViewLink(ByVal columnViewKey As String) As LinkValue
Dim targetListGUID As System.Guid = SPContext.Current.List.Lists(TargetList).ID
Dim fieldValue As String = SPContext.Current.Item(columnViewKey).ToString()
Dim viewGUID As System.Guid = SPContext.Current.List.Lists(TargetList).Views(fieldValue).ID
Dim sbLink As New StringBuilder
sbLink.AppendFormat("/_vti_bin/owssvr.dll?CS=109&Using=_layouts/query.iqy&List={0}{1}{2}", _
"{", targetListGUID.ToString, "}")
sbLink.AppendFormat("&View={0}{1}{2}&CacheControl=1", _
"{", viewGUID.ToString, "}")
Dim tempLink As LinkValue = New LinkValue
tempLink.Description = fieldValue & " - View"
tempLink.Hyperlink = sbLink.ToString
Return tempLink
End Function

We retrieve the list GUID, and then use that to to retrieve the view GUID. Then we are able to format our link querystring to export the spreadsheet. These values are then extracted in the RenderPattern section in the FLDTypes xml. Make sure you have a good understanding of the LinkValue class, which inherits from the SPFieldMultiColumnValue class. The SPFieldMultiColumn is populated with SPFieldMultiColumnValue's, which is what allows us to use the <Column SubColumnNumber="0" HTMLEncode="TRUE" /> format when it comes to display rendering. You could add more properties on the LinkValue class for Alt tags, link targets, images, etc. and access them the same way when rendering.

In the FLDTypes_SpreadsheetLink.xml there are two custom fields in the PropertySchema, ColumnFilter and TargetList. These are the column in which to use as the view name lookup, and the list that the views exist on, respectively. The user sets these values when creating the column. More on Custom Field Type XML here.

On your SharePoint list, if the view does not exist for the filter, when the item is created, the link field will remain blank. Once the view is created, go back in to edit the item, and the link will appear if the view is named correctly.

Disclaimer: The code and information in this post are for reference purposes only. Please check with relevant best practices and standards before implementing in a business environment.

More Information:
Share This Point: v3 Creating Custom Field Types
MSDN: Custom Field Type Definition
Westin's Technical Log: How To Create a Hyperlink to SharePoint's List Export to Spreadsheet

Tuesday, February 26, 2008

CAML with Multi-Value Lookup Fields

When using the WSS 3.0 Web Services to access your lists, you might have a list that contains a Multi-Value Lookup Field; that is to say, a Lookup Field that has the "Allow Multiple Values" option checked. These types of fields are a bit shaky in SharePoint, although some quirks have been addressed in the recent Service Pack 1 upgrade. A regular CAML query to insert a new item would look something like this:

<Method ID="1" Cmd="New">
   <Field Name="FirstName">John</Field>
   <Field Name="LastName">Doe</Field>
   <Field Name="Email\"></Field>

So now you want a field where the user can select multiple items, and these items are populated from another list. Let's say there is a section on a form that allows a user to sign-up for multiple mailing lists. On the back-end these would be managed in their own list, "Mailing Topic", and would be the source for our lookup column. We will call the lookup column "My Subscriptions". Here is the contents of our "Mailing Topic" list:
ID  Topic Name
1    New Hires
2    Promotions
3    Leaving

We will submit the same CAML, but with the new field added and all three options included:

<Method ID="1" Cmd="New">
   <Field Name="FirstName">John</Field>
   <Field Name="LastName">Doe</Field>
   <Field Name="Email\"></Field>
   <Field Name="MySubscriptions\">
      1;#New Hires;#2;#Promotions;#3;#Leaving

The format is: ID#;Lookup Field Value. Separate additional values by ";#". If you look in the list with the lookup column after a successful submission, you will see all the items, but minus the #;ID's and delineated with a comma instead.