Create a user profile synchronisation with c# code

by Bas Hammendorp 19. August 2010 10:01

For a current project I'm working on, we need to script the user profile synchronisation connection so that we can deploy it on our different servers. To do this, you need to take a few different steps.

First you have to open the user profile manager context

// Open the central administration
SPSite centralAdminSite = SPAdministrationWebApplication.Local.Sites[0];

// Open the user profile manager context
SPServiceContext context = SPServiceContext.GetContext(centralAdminSite);
UserProfileManager userProfileManager = new UserProfileManager(context);
UserProfileConfigManager userProfileConfigManager = new UserProfileConfigManager(context);

Then set up the parmaters for the connection

string connectionName = "My Connection"; //
string systemName = "UserProfileLOBSystemInstance"; // The LobSystemInstance name
string entityName = "UserProfileEntity"; // The Entity name
string filterName = ""; // The filter ??
string entityNamespace = "UserProfiles.BdcModel1"; // Namespace of the project
string profilePropertyName = "AccountName"; // The unique SharePoint property to map the BDC to
string mappedAttribute = "ID"; // The unique BDC property

List<DSMLAttribute> dsmlAttributes = new List<DSMLAttribute>();
DSMLAttribute attr = null;

// Loop through all items from some sort of resource, E.G. an XML file
// The DSML attributes seem to be required so the connection knows these properties are available for mapping
// and that these properties can be mapped to a BDC field
foreach (var item in items)
{
   attr = new DSMLAttribute(); // create a new attribute
   attr.Indexible = bool.Parse(item.indexible);
   attr.Name = item.name; // the name of de BDC property
   attr.ID = item.id;
   attr.SingleValued = bool.Parse(item.singledValue);
   attr.Syntax = (DSMLSyntax)Enum.Parse(typeof(DSMLSyntax), item.syntax);
   dsmlAttributes.Add(attr);
}

and finally create the connection

try
{
 // Create the new user profile synchronisation connection
 userProfileConfigManager.ConnectionManager.AddBusinessDataCatalogConnection(
         connectionName, systemName, entityName, entityNamespace, profilePropertyName,
                filterName, mappedAttribute, dsmlAttributes);
}
catch (SystemException sex)
{
 // In some way, sometimes there is thrown an exception when nothing was wrong
}
catch (Exception ex)
{

}

To figure all this stuff out, I needed a lot of reflection and patience. Hope this gives you the right start to work with user profile sync connections.

Have fun!

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | SharePoint 2010

Use external assembly and webservices in sandboxed solutions; create full trust proxy

by Bas Hammendorp 10. July 2010 03:33

Imagine a situation where you want to use the advantages of a sandboxed solution, but also need some extra functions from (for example) a generic library. To accomplish this, you need to create a full trust proxy.

A sandbox solution runs in its own isolated process, the SPUCWorkerProcess.exe (this proces needs to be attached when you need to debug). This process has limited options regarding c# code, access to file system etc. To extend these option, you can write a full trus proxy. There are a few steps to take:

1. Create a new empty sharepoint 2010 (farm) project
In this project you need to create two classes, one class inherits from SPOperation and the other from SPOperationArgs

The first class contains the execute method in where you can execute you code

public class MyProxyOperation : SPProxyOperation
{
   public override object Execute(SPProxyOperationArgs args)
   {
      if (args != null)
      {
         // use the arguments
         MyProxyOperationArgs arguments = args as MyProxyOperationArgs;
        
         try
         {
            // execute your code
         }
         catch (Exception ex)
         {
            return ex.Message;
         }
       }
      return String.Empty;
   }
}

The method Execute is the only method you can use in the class, this should contain the code which you want to execute out of the sandbox. This code runs in the 'normal' w3p process.

The second method contains the arguments which you want to pass to the proxyoperation class:

[Serializable]
public class MyProxyOperationArgs : SPProxyOperationArgs
{
   public string argument1 { get; set; }
   public int argument2 { get; set; }
}

The properties in this class must be serializable.

2. Add the attribute [assembly: AllowPartiallyTrustedCallers()] to the AssemblyInfo.cs of this project so the assembly accepts the calls from the sandbox solution.

3. Create a new empty sharepoint 2010 (sanboxed) project
This project contains the call to the proxyoperation execute method in the previous project.

MyProxyOperationArgs myProxyOperationArgs = new MyProxyOperationArgs();
myProxyOperationArgs.argument1 = "Hello world";
myProxyOperationArgs.argument2 = 101;
                        e
string result = SPUtility.ExecuteRegisteredProxyOperation(
                <full assemblyname>,
                <typename>, myProxyOperationArgs).ToString();

Here you can see that you need to create the proxyoperation arguments, fill the properties and give this to the execute method. To call the execute method, you need to use the SPUtility.ExecuteRegisteredProxyOperation method which contains the full assembly name, the typename (with namespace) and you arguments. This will return an object which you (for example) can cast to a string.

So this should be the way to use additional code in sandboxed solution, but be carefull what to use and what not. After all, the sandbox has some important advantages in security and resources which you don't want to knock down.

One last important tip: when you deploy a new assembly with you proxy operations, you need to restart the SPUsercode service. You can do this with the command line operations 'net stop SPUsercodeV4' and 'net start SPUsercodeV4'

Good luck!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | SharePoint 2010 | Sandbox solution

Update SharePoint workflow approvers, notification message and other properties with object model

by Bas Hammendorp 2. July 2010 06:25

When you setup a workflow in SharePoint UI, there are two screens. One with the general workflow settings and the second to adjust some specific settings like the approvers and the notification message. The first screen is not so hard to update in the object model, the second gives you more headache. You need to change the property AssociationData of the SPWorkflowAssociation which is contains an XML string with several properties, not so intuative.

To make my life a little easier, I have created a wrapper class to update these properties. Hope this helps you out!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.ComponentModel;

namespace myProject
{
    public class WorkflowAssociationData
    {
        #region properties
        public enum AccounTypeOption { User, SharePointGroup };
        public enum AssignmentTypeOption
        {
            [Description("Allemaal tegelijk (parallel)")]   parallel,
            [Description("Eén tegelijk (serieel)")] serial
        };

        public enum DurationUnitsOption
        {
            [Description("Dag(en)")]    day,
            [Description("We(e)k(en)")] week,
            [Description("Maand(en)")]  month
        };

        private XDocument xmlData;
        public XDocument XmlData
        {
            get { return xmlData; }
            set { xmlData = value; }
        }

        public string NotificationMessage
        {
            get { return readNodeValue("NotificationMessage"); }
            set { setNodeValue("NotificationMessage", value); }
        }

        public int DurationforSerialTasks
        {
            get { return int.Parse(readNodeValue("DurationforSerialTasks")); }
            set { setNodeValue("DurationforSerialTasks", value.ToString()); }
        }

        public DurationUnitsOption DurationUnits
        {
            get { return ((DurationUnitsOption)Enum.Parse(typeof(DurationUnitsOption), readNodeValue("DurationUnits"))); }
            set { setNodeValue("DurationUnits", value.GetDescription()); }
        }

        public bool CancelonRejection
        {
            get { return bool.Parse(readNodeValue("CancelonRejection")); }
            set { setNodeValue("CancelonRejection", value.ToString().ToLower()); }
        }

        public bool CancelonChange
        {
            get { return bool.Parse(readNodeValue("CancelonChange")); }
            set { setNodeValue("CancelonChange", value.ToString().ToLower()); }
        }

        public bool EnableContentApproval
        {
            get { return bool.Parse(readNodeValue("EnableContentApproval")); }
            set { setNodeValue("EnableContentApproval", value.ToString().ToLower()); }
        }

        public AssignmentTypeOption AssignmentType
        {
            get { return ((AssignmentTypeOption)Enum.Parse(typeof(AssignmentTypeOption), readNodeValue("AssignmentType"))); }
            set { setNodeValue("AssignmentType", value.GetDescription()); }
        }
        #endregion

        private WorkflowAssociationData() { }

        /// <summary>
        /// Create a new object with the default or existing XML
        /// </summary>
        /// <param name="xml"></param>
        public WorkflowAssociationData(string inputXml)
        {
            XmlData = XDocument.Parse(inputXml);
        }

        /// <summary>
        /// Update the approvers for this workflow
        /// </summary>
        /// <param name="displayName"></param>
        /// <param name="accountName"></param>
        /// <param name="accountType"></param>
        public void UpdateApprovers(string displayName, string accountName, AccounTypeOption accountType)
        {
            insertPersonElement("Assignee", displayName, accountName, accountType);
        }

        /// <summary>
        /// Update the CC receivers for this workflow
        /// </summary>
        /// <param name="displayName"></param>
        /// <param name="accountName"></param>
        /// <param name="accountType"></param>
        public void UpdateCc(string displayName, string accountName, AccounTypeOption accountType)
        {
            insertPersonElement("CC", displayName, accountName, accountType);
        }

        /// <summary>
        /// Attach the person element to the node <nodeName>
        /// </summary>
        /// <param name="nodeName"></param>
        /// <param name="displayName"></param>
        /// <param name="accountName"></param>
        /// <param name="accountType"></param>
        private void insertPersonElement(string nodeName, string displayName, string accountName, AccounTypeOption accountType)
        {
            XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
            XNamespace pc = ""http://schemas.microsoft.com/office/infopath/2007/PartnerControls">http://schemas.microsoft.com/office/infopath/2007/PartnerControls";

            XElement dElement = XmlData.Descendants(d + nodeName).First();
            if (dElement.Descendants().Count() == 0)
            {
                XElement el = new XElement(pc + "Person",
                                    new XElement(pc + "DisplayName", displayName),
                                    new XElement(pc + "AccountId", accountName),
                                    new XElement(pc + "AccountType", accountType.ToString())
                                );
                dElement.Add(el);
            }
        }

        private string readNodeValue(string name)
        {
            XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
            XElement el = XmlData.Descendants(d + name).First();
            return el.Value;
        }

        private void setNodeValue(string name, string value)
        {
            XNamespace d = ""http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields";
            XElement el = XmlData.Descendants(d + name).First();
            el.Value = value;
        }
    }

    public static class EnumMethods
    {
        /// <summary>
        /// Get the description from the enum
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetDescription(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
        }
    }
}

An example to use this class:

// defaultXml is the default XML from a new SPWorkflowAssociation
WorkflowAssociationData data = new WorkflowAssociationData(defaultXml);
data.UpdateApprovers("Site Approvers Group", "Site Approvers Group", WorkflowAssociationData.AccounTypeOption.SharePointGroup);
data.NotificationMessage = "Please approve this item";
workflowAssociation.AssociationData = data.XmlData.ToString();

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | SharePoint 2010 | Workflow

Set option 'start this workflow to approve publishing a major version of an item' in c#

by Bas Hammendorp 1. July 2010 05:36

Today i was trying to figure out how to set the option 'Start this workflow to approve publishing a major version of an item' on my SharePoint list workflow. After some research I found out that the way to go is this:

  1. Cast the SPList object to an SPDocumentLibrary
  2. Attach the workflow to the document library object
  3. Set the DefaultContentApprovalWorkflowId
  4. Update the list

The code will be something like this:

// list is an SPList object, workflowAssociation is an SPWorkflowAssociation object
SPDocumentLibrary docLib = (SPDocumentLibrary)list; // cast
docLib.WorkflowAssociations.Add(workflowAssociation); // attach
docLib.DefaultContentApprovalWorkflowId = workflowAssociation.Id; // set property
list.Update(); // save the list

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | SharePoint 2010 | Workflow

New version of the WSP Listener

by Bas Hammendorp 17. May 2010 09:12

Finally after lots of coding, testing and feedback; I have the new WSP listener ready. You can download it from codeplex.

In short, the improvements:

  • All assemblies and required assets in one WSP
  • Seperated code in library assembly
  • Activate the WSP Listener with one simple feature
  • Clear overview of (previous) installations in one document library
  • Several bugfix and code improvements

Hope you like it as much as I do.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Sharepoint | Tools

Upload a file in central admin document library

by Bas Hammendorp 16. May 2010 09:15

I was making a simple console application to upload a zip file (with a WSP Listener solution) in the document library. This document library was located in the central admin, so I also wanted to find the central admin web application dynamic. I came up with the next solution:

// Set the path to the zip file and the name of the document library
string path = "c:\temp\testfile.zip";
string documentLibraryName = "WSPListener document library";

// Get the central administration web application and the upload folder
SPWeb centralAdminWeb = SPAdministrationWebApplication.Local.Sites[0].OpenWeb();
SPFolder uploadFolder = centralAdminWeb.Folders[documentLibraryName];
bool replaceExistingFiles = true;

SPFolder myLibrary = centralAdminWeb.Folders[documentLibraryName];

// Open a file stream to add the file in the document library
using (FileStream fileStream = File.OpenRead(path))
{
   SPFile spFile = myLibrary.Files.Add(fi.Name, fileStream, replaceExistingFiles);
   myLibrary.Update(); // save the file

   // Get the corresponding SPItem to update some properties and start the installation
   SPListItem item = spFile.Item;
   item["InstallationStartTime"] = null;
   item["InstallationEndTime"] = null;
   item["InstallationStatus"] = "Install";
   item["InstallationResult"] = "";
   item.Update();
}

As you can see, it's very easy :)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C# | Sharepoint

Nice link with SharePoint 2010 installation instructions

by Bas Hammendorp 29. March 2010 03:54

While I was installing SharePoint 2010, I found the next link which helped me out : http://www.codeproject.com/KB/sharepoint/SharePoint_Server_2010.aspx

Have fun!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

SharePoint 2010

Save a file to disk from a document library

by Bas Hammendorp 13. March 2010 07:17

In my new update for the WSP Listener I need to save a file from a document library to disk. This can be done by the following code:

// item is an SPListItem
SPFile myFile = item.File;
DestinationFile = Path.Combine(@"c:\temp", myFile.Name);
if (File.Exists(DestinationFile))
{
   // Remove the old file
   File.Delete(DestinationFile);
}

// Open the binary data
byte[] data = myFile.OpenBinary();
using (FileStream stream = new FileStream(DestinationFile, FileMode.CreateNew))
{
   // Save the file
   BinaryWriter writer = new BinaryWriter(stream);
   writer.Write(data, 0, (int)myFile.Length);
   writer.Close();
   stream.Close();
}

Have fun!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

C# | Sharepoint

My first codeplex: WSP Listener

by Bas Hammendorp 8. March 2010 06:53

Finally my first codeplex project is finished: http://wsplistener.codeplex.com/

Super easy copy paste installation of WSP files on different servers in your OTAP environments.

The WSP listener is a windows service application which waits for new config and WSP files in a specific folder. If a new config and WSP file are added, the WSP Listener will install the new SharePoint solution on the server based on values in de config file. The config file is a configuration file (for example MySharePointSolution.wsp.config) which defines the settings for the installation of the WSP solution file.

All feedback is welcome, hope this tool helps improvethe efficiency of your deployment

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Sharepoint | Tools

Update site columns in existing environment with feature

by Bas Hammendorp 4. March 2010 09:45

So I had this problem with updating site columns in existing site collections. I use a feature with element XML to install my custom site columns in the site collections. The problem is when I try to update some property of an existing site column, for example set required to TRUE, the update cannot be done by reinstalling the changed site column feature. After I reinstalled my updated site columns feature, no changes are comitted in the site columns of my site collection.

I tried ststadm -o deactivatefeature, then stsadm-o installfeature -force, ststadm -o activatefeature with some IISRESET's in between

So what is this hidden solution for this problem? Well the Field nodes in the element file has this strange property DisplaceOnUpgrade, set this to TRUE and the columns will be updated. The explanation from Microsoft:

DisplaceOnUpgrade: Optional Boolean. If a field definition already exists for the field, TRUE to force updates to field properties with the values that are specified in this field definition. Check the link for more info.

Hope this helps you!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Sharepoint

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

My name is Bas Hammendorp, I work as an Enterprise Engineer at PGGM. My specialties are ASP.NET, C#, SQL and Sharepoint 2007.

Google ads