Showing posts with label SharePoint 2010. Show all posts
Showing posts with label SharePoint 2010. Show all posts

Thursday, January 27, 2011

Workflow Action : Attach Document to ListItem

I have been really disapointed when realizing that I couldn't Attach a document to an item when I designed a workflow. So, to me this action was definitly missing. I needed it in a document library list with incoming email feature activated in order to be able to send emails to this library and those emails to be managed to be linked automatically to other items in other lists... For this custom activity, I have been assisted a member of my team: Yassine Hachime.


I won't explain here The principle on How to create Custom Activity on Sharepoint 2010, this topic has already been explained several times on the web :

http://www.chaholl.com/archive/2010/03/13/make-a-custom-activity-available-to-sharepoint-designer-2010.aspx or
http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/4e7a77f4-c29b-47b2-a1de-79470f0bb1c9


My plan is just to give you one more action to add to your SPD.
I will just provide you the code for the action file and the bin. I'll leave you the rest of the job.


Here is the action file :



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

<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="Attach Doc to Item"
ClassName="AttachMailWFActivity.AttachDocToItem"
Assembly="AttachMailWFActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=46f60639ee1bfb57"
AppliesTo="all" Category="List Actions">
<RuleDesigner Sentence="Attach %1 to %2">
<FieldBind Text="this document" Field="LibId,DocItem" DesignerType="ChooseDoclibItem" Id="1" />
<FieldBind Text="this item" Field="ListId,ListItem" DesignerType="ChooseListItem" Id="2"/>
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" />
<Parameter Name="LibId" Type="System.String, mscorlib" Direction="In" InitialBinding="__list"/>
<Parameter Name="DocItem" Type="System.Int32, mscorlib" Direction="In" InitialBinding="__item" DesignerType="ListItem" Description="ID of the list item used by this action." />
<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In"/>
<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" DesignerType="ListItem" Description="ID of the list item used by this action." />

</Parameters>
</Action>

</Actions>

</WorkflowInfo>



And the code of the
AttachMailWFActivity.AttachDocToItem assembly is :



using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Linq;
using System.IO;
using Microsoft.SharePoint;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using Microsoft.SharePoint.WorkflowActions;
using System.Workflow.Activities.Rules;

namespace TSP.AttachMailWFActivity
{
public partial class AttachDocToItem : Activity

{

public static DependencyProperty LibIdProperty = DependencyProperty.Register("LibId", typeof(string), typeof(AttachDocToItem));
public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(AttachDocToItem));
public static DependencyProperty DocItemProperty = DependencyProperty.Register("DocItem", typeof(Int32), typeof(AttachDocToItem));
public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(Int32), typeof(AttachDocToItem));
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(AttachDocToItem));

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[Description("ID of the document library storing the doc that will be attached to the item")]
public string LibId
{
get { return ((string)(base.GetValue(AttachDocToItem.LibIdProperty))); }
set { base.SetValue(AttachDocToItem.LibIdProperty, value); }
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[Description("ID of the list keeping the item to which the document will be attached to")]
public string ListId
{
get { return ((string)(base.GetValue(AttachDocToItem.ListIdProperty))); }
set { base.SetValue(AttachDocToItem.ListIdProperty, value); }
}

[Description("ID of the list item to which the document will be attached to")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Int32 ListItem
{
get { return ((Int32)(base.GetValue(AttachDocToItem.ListItemProperty))); }
set { base.SetValue(AttachDocToItem.ListItemProperty, value); }
}

[Description("ID of the document item to which the document will be attached to")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Int32 DocItem
{
get { return ((Int32)(base.GetValue(AttachDocToItem.DocItemProperty))); }
set { base.SetValue(AttachDocToItem.DocItemProperty, value); }
}

[Description("Context")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(__ContextProperty))); }
set { base.SetValue(__ContextProperty, value); }
}


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
try
{

__Context.Web.AllowUnsafeUpdates = true;

Guid id = new Guid(ListId);
SPList list = __Context.Web.Lists[id];
Guid did = new Guid(LibId);
SPList docLib = __Context.Web.Lists[did];
SPListItem sourceItem = docLib.GetItemById(DocItem);
SPFile sourceDoc = sourceItem.File;
byte[] fichierbyte = sourceDoc.OpenBinary();

SPListItem destinationItem = list.GetItemById(ListItem);
destinationItem.Attachments.Add(sourceItem.Name, fichierbyte);
destinationItem.Update();
return ActivityExecutionStatus.Closed;

}
catch (Exception Ex)
{

return ActivityExecutionStatus.Faulting;
throw new Exception(Ex.Message + "&&&&" + Ex.StackTrace);

}
finally
{

}
return ActivityExecutionStatus.Closed;
}

public AttachDocToItem()
{
InitializeComponent();
}
}
}




Now you've got that.
Just :
- Create a sharepoint 2010 empty project
- Create a class and copy the code
- Create an action file and copy the code
- Sign your assembly
- Package your wsp
- Install the wsp on you WFE. Deploy it.
- Add the correct line in the AuthorizedType tag of your web.config.


The result :



(for the capture... it's because my SPD Is in french)


I hope it helps.
Don't hesitate to contact me whether you are in trouble using it !!!


Item Created Workflow won't start with incoming email document uploaded

Hello,

It's been a while since my last post.
I was not in the mood ;) (or overloaded with work)... I have a few post to write... I hope it will be done in the few next days. I'm planning to explain the last SPD WF Action I have written (Attach Document to Item)....

But right now my post just describes a problem with the library with incoming email feature activated. When you send an email to the library, the automatic workflow launched at item created are simply not raised. It works for the items you add normally though.

Workaround?
Yeess. I found this post http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/810d0273-06f3-4815-b690-86d0fc880919

So, you just have to run this command line :

Stsadm -o setproperty -pn declarativeworkflowautostartonemailenabled -pv true


It worked for me !!!

Friday, July 30, 2010

Sharepoint 2010 - Create an Audience based ACL

I have been asked to manage the security of an application according to the user profile organization's property.... Well obviously, sharepoint is not designed like that. So, how to ?

My solution is the following :
  • Fill the organization property on each of the profile
  • Create one audience per organization based on this property
  • Synchronize the audiences with Sharepoint groups using a timer job (that's the main part of the article)
I won't explain the two first points, I guess you already know how to create and compile audiences, else go back to the root first !

The principle of my timer job is simple. It is activated using a feature that is scoped webapplication. The execute method parses all the sites of the applications, and the audiences of the platform. It thus verify that a group with the same name exists on the site. If not, it creates the groups, If it does exist, it just adds the users in the group.
So at the end I have on all my sites, the same groups with the same users and everything is based on the audiences that are based on the user profile properties ... Quod Erat Demonstratum.

Below the execute Method of the Timer job:

try
{
SPWebApplication webApplication = this.Parent as SPWebApplication;
AudienceManager audManager = new AudienceManager(SPServiceContext.GetContext(webApplication.Sites[0]));
foreach (SPSite site in webApplication.Sites)
{
foreach (Audience au in audManager.Audiences)
{
try
{
if (site.RootWeb.SiteGroups[au.AudienceName] == null)
{
}
}
catch (Exception exx)
{
SPUser oUser = site.RootWeb.Users.GetByEmail("alexandre.joly@toto.com");
SPMember oMember = site.RootWeb.Users.GetByEmail("alexandre.joly@toto.com");
site.RootWeb.SiteGroups.Add(au.AudienceName, oMember, oUser, "Group synchronized on existing audience");

}
SPGroup group = site.RootWeb.SiteGroups[au.AudienceName];
ArrayList members = au.GetMembership();
if (members != null)
{
foreach (UserInfo userInfo in members)
{
group.Users.Add(userInfo.NTName, userInfo.Email, userInfo.PreferredName, "");
}
}
}
}

}
catch (Exception exc)
{

}

Thursday, June 24, 2010

Migrating Sharepoint 2010 Beta to RTM

As most of you may have seen... migrating Beta to RTM is not something supported by MS. Of course, we all understand that the corrected bug of the beta may cause problem on you newly installed flashy RTM Platform... BUT... some of us (at least me) have been asked to put in production a beta platform... and now.. with 10000 items in a list... what can I do ? hiring 100 persons to recreate my items ... obviously not So let's find a way..

  1. Using the Backup site collection feature in the central admin on your beta platform, back up the entire site collection that contain you web or you list (dont try to' export only list or webs using powershell commands, it simply doesn't work (version conflicts).
  2. Using the restore-spsite powershell command to restore your site collection on your new platform...
  3. Yessss! Now you have you data on you new platform.. YESSSSS, it feels already better... (OOOH Damned.. I have lost my term store connection, arrrg)
  4. use the Content deployment wizard tool of Cris O Brien (Sharepoint MVP) to migrate content from your site collection to your new site. In my case I only had to migrate 3 big lists with content types.
in my case, I had to launch several other scripts to resolve my term store connection problem (I parse my old list to find the termstores values and I pars my new list to put back those values....)
I'm sure it can work without doing that but I didn't find the way !


Good luck

Wednesday, January 27, 2010

Term Store and views

After a 2 months using sharepoint 2010 every days, I have extracted in this new version a wonderfull feature : the term store. It allowed us to simplify a lot the architecture.

Now, the list of customers and projects to which the data is linked all around the information system is tagged using termsets. Easy to create, easy to maintin.

Before I had to create linked list to simulate the hierarchy... now, everything is done my itself.

I won't make a all blog on this feature, some other blogs already did it :
http://www.wssdemo.com/Blog/Lists/Posts/Post.aspx?List=b853926a-b04e-4620-94e4-88a5d56cb262&ID=494&Web=d47402ad-1767-42ba-a072-133479a9bb5a
or
http://www.cmswire.com/cms/document-management/overview-sharepoint-2010-metadata-and-taxonomy-management-006015.php


One bad point though... This morning I wanted to create views grouped by my customer column (which is a managed metadata column), How disappointing it was when I noticed that It was simply impossible :( Those kind of column don't appear in the list.

So be aware that grouping and sorting is not available for Managed metadata columns.

Friday, December 18, 2009

SharePoint 2010 Beta Documentation

For some weeks, I have been looking around for help on sharepoint 2010... hard to find, we are almost all at the same level.

I have found this doc published a few days ago on technet :
http://technet.microsoft.com/en-us/library/cc303422%28office.14%29.aspx

That's a good starting point !!!

SharePoint 2010, and InfoPath 2010 for Form customization

It's been a while sinc my last post. for a month I have been working fully on the Sharepoint 2010 Beta.
I have a really good feeling with the product that has some really good improvment :
  • I love the taxonomy system
  • I love the ribbon
  • I love the form displayed on a layer (finally!!!)
  • I love the performance services...
...But there is something I have been Hating those last 2 days...

I have a VS2010 Solution containing new types (Located in 14/templates/XML/fldTypes_xxx.xml) that have a custom rendering (let's say two texteboxes). Those types are used in a content type I have developped too. This content type is used in a list.
Because it makes a big form, I have tried the form customization feature with Infopath...
I have been a bit disapointed...

All my custom fields that have a non standard type cannot be added on the infopath form (it mentions that when infopath is starting). So it means that I can customize my form but only without thos fields.. Useless for me... Sh**

I'm trying to find a way to integrate thos types in infopath 2010.. So far.. nothing...