dinsdag 12 januari 2010

Custom people field in SharePoint 2007

Some time ago I needed to create a people field which had to have a default value. The default value had to be the current user. This is not possible out of the box so I needed to create a custom field type for this. Because there was very little information on creating a custom people field on the net, I will explain the method in this post.

1. Create the custom field xml
This file needs to go in 12/TEMPLATE/XML. Make sure it starts with 'fldtypes_'. I will call it 'fldtypes_customPeopleField'.

Here is the xml. It will describe some properties of this field like the type name, displayname and the class which will take care of the actual logics.

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



   2: <FieldTypes>



   3: <FieldType>



   4: <Field Name="TypeName">CurrentUserAsDefault</Field>



   5: <Field Name="ParentType">User</Field>



   6: <Field Name="TypeDisplayName">Current User</Field>



   7: <Field Name="TypeShortDescription">People field with current user as default value</Field>



   8: <Field Name="UserCreatable">TRUE</Field>



   9: <Field Name="ShowInListCreate">TRUE</Field>



  10: <Field Name="ShowInSurveyCreate">TRUE</Field>



  11: <Field Name="ShowInDocumentLibrary">TRUE</Field>



  12: <Field Name="ShowInColumnTemplateCreate">TRUE</Field>



  13: <Field Name="FieldTypeClass">MyProject.ContentTypes.CurrentUserField, MyProject.ContentTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f443cebe7d24f267</Field>



  14: <Field Name="FieldEditorUserControl">/_controltemplates/UserFieldEditor.ascx</Field>



  15: <Field Name="Sortable">TRUE</Field>



  16: <Field Name="Filterable">TRUE</Field>



  17: <RenderPattern Name="DisplayPattern">



  18: <FieldSwitch>



  19: <Expr>



  20: <Property Select="FieldRef"/>



  21: </Expr>



  22: <Case Value="">



  23: <Switch>



  24: <Expr>



  25: <Column/>



  26: </Expr>



  27: <Case Value="">



  28: <FieldSwitch>



  29: <Expr>



  30: <Property Select="SuppressNameDisplay"/>



  31: </Expr>



  32: <Case Value="TRUE">



  33: <HTML><![CDATA[<table cellpadding=0 cellspacing=0 dir="]]></HTML>



  34: <Property Select="Direction" HTMLEncode="TRUE"/>



  35: <HTML><![CDATA["><tr><td style="padding-right: 3px;">]]></HTML>



  36: <HTML><![CDATA[ <img border="0" valign="middle" height="12" width="12" src="/_layouts/images/blank.gif" > </td></tr></table>]]></HTML>



  37: </Case>



  38: </FieldSwitch>



  39: </Case>



  40: <Default>



  41: <FieldSwitch>



  42: <Expr>



  43: <Property Select="LookupType"/>



  44: </Expr>



  45: <Case Value="Computed">



  46: <LookupColumn/>



  47: </Case>



  48: <Default>



  49: <LookupColumn HTMLEncode="TRUE"/>



  50: </Default>



  51: </FieldSwitch>



  52: </Default>



  53: </Switch>



  54: </Case>



  55: <Default>



  56: <LookupColumn HTMLEncode="TRUE"/>



  57: </Default>



  58: </FieldSwitch>



  59: </RenderPattern>



  60: </FieldType>



  61: </FieldTypes>







2. Create the logic


For the actual logics, I will create a class which inherits from SPFieldUser and I will override the 'DefaultValue' property.









   1: namespace MyProject.ContentTypes



   2:  



   3: {



   4:  



   5: public class CurrentUserField : SPFieldUser



   6: {



   7:  



   8: public CurrentUserField(SPFieldCollection fields, string fieldName, string displayname) : base(fields, fieldName, displayname){}



   9: public CurrentUserField(SPFieldCollection fields, string fieldName) : base(fields, fieldName){}



  10:  



  11: public override string DefaultValue



  12: {



  13:  



  14: get



  15: {



  16:  



  17: SPWeb web = SPContext.Current.Web;



  18:  



  19: SPUser user = web.CurrentUser;



  20:  



  21: string defaultValue = string.Format("{0};#{1}", user.ID.ToString(), user.Name);



  22:  



  23: if (this.SelectionGroup > 0)



  24: {



  25:  



  26: SPGroup group = web.Groups[this.SelectionGroup];



  27:  



  28: if ((group != null) && (group.ContainsCurrentUser))



  29:  



  30:    return defaultValue;



  31:  



  32: }



  33: else



  34: {



  35:  



  36:    return defaultValue;



  37:  



  38: }



  39:  



  40:    return string.Empty;



  41:  



  42: }



  43:  



  44: set



  45: {



  46:  



  47:    base.DefaultValue = value;



  48:  



  49: }



  50:  



  51: }



  52:  



  53: }



  54:  



  55: }








What it will do is set the current user as the default value. The setter we will leave untouched and therefore we just use the one from SPFieldUser.





3. Using the custom field


You can now use this custom field to create a custom column:









   1: <Field



   2:     Type="CurrentUserAsDefault"



   3:     DisplayName="My Custom User Field"



   4:     List="UserInfo"



   5:     ShowField="ImnName"



   6:     UserSelectionMode="0"



   7:     UserSelectionScope="0"



   8:     Group="Custom"



   9:     ID="{0ab09806-9434-4e11-bedd-d232614089b2}"



  10:     SourceID="{ac48197d-8e5a-4207-bf24-6615f4bb857f}"



  11:     StaticName="CurrentUserAsDefault"



  12:     Name="CurrentUserAsDefault"



  13: />





4. Deployment


Just create a wsp solution file and make sure the field xml is placed in the correct folder. Normally this field type should also popup in the GUI when you want to create a new site column.





5. Sidenotes


I have understood that this custom field (and possibly all custom fields) are not supported by Colligo, an offline tool for SharePoint. By not supported I mean I wasn't able to update this field. It was just read-only. Just so you know :) .

dinsdag 5 januari 2010

Exporting a SharePoint 2010 workflow into Visual Studio 2010

Hi everybody and my excuses for the long silence but the last weeks of the year and by that all the festivities, also took their tole one me :)

In this article I will show you how you can create a workflow in SharePoint Designer 2010, export it and then import it in Visual Studio 2010 for further extending.

One of the great new things in SharePoint Designer 2010 is the possibility to export created workflows to use them in Visual Studio 2010. Like this it's now much more easier for power users to design workflows and give them to a developer who can further extend this workflow in Visual Studio 2010.

1. Create a workflow in SharePoint Designer
Startup SPD and connect to your site collection. Go to 'Workflows' and click on 'Reusable workflow' to create a new reusable workflow.

Give it a name and a description and choose the content type for which this workflow will be available.

2. Design the workflow
You can now start using all the conditions and actions provided by SPD to create your workflow. I created a very simple workflow which will set the workflow status to 'Cancelled' if the current item's title field equals "Title1". Else the status will be set to 'Approved'.

You can click on 'Check for errors' if you want so you are sure that you used all components correctly.

Save the workflow. SPD will now create all the necessary files for the workflow.




3. Exporting the workflow
Now in SharePoint 2010 beta, you cannot just use the 'Save as Template' button to create a wsp file for this workflow. You would think this function works alright but when you try to import this wsp into a Visual Studio 2010 project, an error will appear saying "Parameter name - Relative path". This issue is known by Microsoft. It's due to a problem in the export function which is not handled correctly in Visual Studio.

A workaround for this, is to export the complete site as a template. To do this, click on your site collection on the left (the button with the house icon). On the top, in the ribbon, you can select 'Save as template'. This will launch the template creation aspx page. Choose a file name and template name. You don't need to 'Include Content'. Click ok to start the template creation.

After completion, click on the provided link to go to the 'user solution gallery'. From there, you can download the wsp file to your drive.

4. Importing the workflow wsp into Visual Studio 2010
Start Visual Studio and create a new SharePoint 2010 project of type 'Import Reusable Workflow'. Type in the URL to your site collection and on the next screen, point the wizard to the site template wsp file. The wizard will analyze this file and present you with a list of all the reusable workflows it could find.

Choose your new workflow and click Finish. This will load the workflow as a new project in the solution. As you can see, the template includes a feature, a package and the actual workflow including the xoml, the rules and cs code file.




Double clicking the xoml file will load the designer view. The names of the activities may not be the best chosen but at least the design itself is unchanged. Like in 2007, you can start adding activities and conditions.

The actual rules we defined in SPD, are stored in the rules file. No actual c# code is generated. Just to be clear, the workflows are based in .NET framework 3.5 and not on version 4.0.

You can now start to extend the workflow with custom code, create a wsp file and use it in your site collection.