I have a colleague (Nicolas Corchia - Sogeti) who came into my office with a migration 2007>2010 problem.
The 2007 Codes analysed a webpartpage in order to find the ListViewWebpart included in it in order to modify them...
Well... after the migration...no more listViewWebpart were found... He came out with the fact that sharepoint automatically changed the listviewPart by the new XsltListViewWebPart class.
Because nicolas is a good developer ;-) he found out that the problem was wimply a casting problem obliging him to recast the webparts in the code itself!
Find more in : http://msdn.microsoft.com/fr-fr/library/ff806162.aspx
Thanks to a problem raised by Nicolas Corchia (Sogeti),
12 years of work within the Sharepoint world : let's talk about technical and functional thoughts around Sharepoint.
Thursday, November 17, 2011
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 :
And the code of the AttachMailWFActivity.AttachDocToItem assembly is :
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 !!!
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 !!!
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 !!!
Thursday, December 23, 2010
Display an exchange public calendar inside sharepoint
To display an Exchange public calendar inside a sharepoint page use a pageviewer webpart, and choose the url this way
https://your_exchange_server/owa/?cmd=contents&module=PublicFolders&f=Calendar
(don't use that kind of url , https://your_exchange_server/public/Calendar/?view=monthly, you may have access is denied error )
https://your_exchange_server/owa/?cmd=contents&module=PublicFolders&f=Calendar
(don't use that kind of url , https://your_exchange_server/public/Calendar/?view=monthly, you may have access is denied error )
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 :
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)
{
}
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)
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..
I'm sure it can work without doing that but I didn't find the way !
Good luck
- 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).
- Using the restore-spsite powershell command to restore your site collection on your new platform...
- 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)
- 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.
I'm sure it can work without doing that but I didn't find the way !
Good luck
Monday, March 1, 2010
Sharepoit 2010 - Search service application
One of the multiple evolutions of the last version of Sharepoint upon the last one is how Sharepoint manages the different services.
Bye bye Shared Service Provider (SSP), Hello the Services applications.
The management of those applications is accessible via the "manage Service applications" of the central admin page.
Yesterday I had a super search app that was working fine with all my scopes and metadatas. Sounded good, no?
Obviously, it's when things go the best that some ununderstandable sh.t happens... In my event viewer, from yesterday nigth til now and every minutes, I had a message saying that my crawl DB wasn't accessible. Damned What have I done??
So as a solution I tried to reset all my indexes... Nope..
I then tried to detach and attach the Search App db... Nope...
I finally decided to save all my settings and to delete my search application (and all the DBs and to recreate it (I'd rather take 1h to do this instead of asking myself the all day "what the fuck wht the fuck"
Here I am now... I can't create a search application : the form opens asking me the app pools and the account , and after a minute and 31 seconds... I have this error
"
Errors were encountered during the configuration of the Search Service Application.
System.Data.SqlClient.SqlException: User does not have permission to perform this action. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command) at Microsoft.Office.Server.Data.SqlServerManager.GrantLogin(String user) at Microsoft.Office.Server.Search.Administration.SearchDatabase.GrantAccess(String username, String role) at Microsoft.Office.Server.Search.Administration.SearchDatabase.SynchronizeAccessRules(SearchServiceApplication searchApp) at Microsoft.Office.Server.Search.Administration.SearchServiceApplication.SynchronizeDatabases() at Microsoft.Office.Server.Search.Administration.SearchServiceApplication.Provision() at Microsoft.Office.Server.Search.Administration.SearchConfigWizard.b__22() at Microsoft.Office.Server.Search.Administration.SearchAdminUtils.UpdateIgnoreSPUpdatedConcurrencyException(String description, SearchAdminUtilsUpdateDelegate updateDelegate, SearchAdminUtilsRefreshObjectDelegate refreshObjectDelegate) at Microsoft.Office.Server.Search.Administration.SearchConfigWizard.CreateSearchApp() at Microsoft.Office.Server.Search.Administration.SearchConfigWizard.ProvisionSearchServiceApplication() at Microsoft.Office.Server.Search.Administration.SearchConfigurationJobDefinition.ExecuteTimerJob()
"
Ooupppppps, so... so far.... no search service for my users :-/
Mmmm, let's check what could have happened ...
This line is interesting " Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command) at Microsoft.Office.Server.Data.SqlServerManager.GrantLogin(String user) "
Am I having SQLServer secrutiy troubles??
If I check the security settings in SQL Server on my staging environment and on my production environment I notice that my service account on my production environment doesn't have the "SecurityAdmin" right ... DAMNED ! I GOT YOUUUUUUU !!
Retry...
YESSSSSSSSSS !
Bye bye Shared Service Provider (SSP), Hello the Services applications.
The management of those applications is accessible via the "manage Service applications" of the central admin page.
Yesterday I had a super search app that was working fine with all my scopes and metadatas. Sounded good, no?
Obviously, it's when things go the best that some ununderstandable sh.t happens... In my event viewer, from yesterday nigth til now and every minutes, I had a message saying that my crawl DB wasn't accessible. Damned What have I done??
So as a solution I tried to reset all my indexes... Nope..
I then tried to detach and attach the Search App db... Nope...
I finally decided to save all my settings and to delete my search application (and all the DBs and to recreate it (I'd rather take 1h to do this instead of asking myself the all day "what the fuck wht the fuck"
Here I am now... I can't create a search application : the form opens asking me the app pools and the account , and after a minute and 31 seconds... I have this error
"
Errors were encountered during the configuration of the Search Service Application.
System.Data.SqlClient.SqlException: User does not have permission to perform this action. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command) at Microsoft.Office.Server.Data.SqlServerManager.GrantLogin(String user) at Microsoft.Office.Server.Search.Administration.SearchDatabase.GrantAccess(String username, String role) at Microsoft.Office.Server.Search.Administration.SearchDatabase.SynchronizeAccessRules(SearchServiceApplication searchApp) at Microsoft.Office.Server.Search.Administration.SearchServiceApplication.SynchronizeDatabases() at Microsoft.Office.Server.Search.Administration.SearchServiceApplication.Provision() at Microsoft.Office.Server.Search.Administration.SearchConfigWizard.
"
Ooupppppps, so... so far.... no search service for my users :-/
Mmmm, let's check what could have happened ...
This line is interesting " Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command) at Microsoft.Office.Server.Data.SqlServerManager.GrantLogin(String user) "
Am I having SQLServer secrutiy troubles??
If I check the security settings in SQL Server on my staging environment and on my production environment I notice that my service account on my production environment doesn't have the "SecurityAdmin" right ... DAMNED ! I GOT YOUUUUUUU !!
Retry...
YESSSSSSSSSS !
Subscribe to:
Posts (Atom)