How to delete multiple attachments in SharePoint

using (SPSite site = new SPSite(@"http://moss2010/WorkFlowCenter"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;
                    SPList list = web.Lists["Booking"];
                    SPListItem item = list.GetItemById(10);

                    SPAttachmentCollection attachmentCollection = item.Attachments;
                    List<String> attachmentList = new List<string>();

                    for (int i = 0; i < attachmentCollection.Count; i++)
                    {
                        attachmentList.Add(attachmentCollection[i]);
                        
                    }

                    for (int i = 0; i < attachmentList.Count; i++)
                    {
                        item.Attachments.Recycle(attachmentList[i]);
                    }
                    item.Update();
                }
            }




RegistrationType & RegistrationId in SharePoint 2010 declarative Ribbon customizations

RegistrationType and RegistrationId attributes of <CustomAction> element are being used in the declarative SharePoint 2010 user interface customizations when they target any list/library related Ribbon UI.
RegistrationType and RegistrationId attributes works in pair only. They form a combination where RegistrationType is a type of criterion for applying customization and RegistrationId is a value of this criterion to compare with content.



What is "content"?
What is "content" with respect to declarative SharePoint Ribbon customization? It's a list/library or a single list item. Where does SharePoint assess that current declarative Ribbon customization is applicable to content? It does it on any page where there is at least one of the standard list view web parts (ListViewWebPart, DataViewWebPart etc.) or list item web parts (ListFormWebPart, DataFormWebpart etc.). It's true for all standard (i.e. generated by SharePoint) list view forms and new/edit/display list item forms because they contain one of such web parts. It also works for any page where such web part is added manually.
For the list view web parts SharePoint analyzes the list itself and its content types but ignores items in this list. In case of single list item web part SharePoint analyzes the list, the content type of list item and a file if the list item is document library item.

Unsupported content
There are some types of content where SharePoint doesn't apply any SharePoint Ribbon declarative customizations for some unknown reasons. One of such types is "Picture Library" (base list template 109). The picture library exception is hardcoded in SharePoint code. So you can apply your customization to image files in general document library by file extension (see the FileType section below) or by content type but you can't apply customizations if image files stored in picture library.

RegistrationType
RegistrationType can have one of four hardcoded values – "List", "ContentType", "FileType" and "ProgId" with exact letter case. The applicability of these values depends on context – is current content list or library or a single list item or a single library item (i.e. item with file):
RegistrationType List List Item Library Library Item
List + + + +
ContentType + + + +
FileType


+
ProgId


+
RegistrationId
RegistrationId is a string which format depends on the chosen RegistrationType.

"List"
Despite the "List" name you can't use this type of registration with list unique identifier, title, URL or any other list property. RegistrationId for the "List" RegistrationType must correspond to the base list template identifier of the list where customization should appear. This identifier is always an integer from the hardcoded range. So this type of registration allows limiting of declarative Ribbon customization to some class of lists but not to specific list instances.

What if you need to apply customization to a single list instance?
You can use other types of registration. For example you can create an unique content type for your list and apply customization to this content type (see the ContentType section below). Another way is to customize Ribbon programmatically.

While applying Ribbon customization on pages with standard list view webparts and list item web parts (see the "What is "Content" section above) SharePoint compares RegistrationId value in "List" registrations to a base value of Microsoft.SharePoint.SPListTemplateType enumeration member which is stored in Microsoft.SharePoint.SPList.BaseTemplate property of the list being assessed.

According to some information there is additional range of identifiers not included in SPListTemplateType enumeration. These identifiers don't used in Ribbon customization for standard webparts and it's unclear how and where they are used.

The most complete known list of base template identifiers including non standard (i.e. not included in SPListTemplateType enumeration) is listed here.
Here is an example of registration (please note that in current example and in following examples other required attributes of <CustomAction> element ommited for simplicity):

<CustomAction RegistrationType="List" RegistrationId="101">

"ContentType"
RegistrationId for this type of registration must correspond to content type identifier of the content where customization is required. Content type identifier is a string of specific format and looks like «0x0100A33D9AD9805788419BDAAC2CCB37509F». While applying customization in the context of a single list item SharePoint gets this identifier from SPListItem.ContentTypeId property. In the list context Sharepoint gets it from the content type collection of current list (SPListItem.ContentTypes). The case is important. The value of RegistrationId must be equal to the whole target content type id or at least to the beginning of it. Content type identifiers have a recursive structure and always contain identifiers of all parents. So this type of registration is always applied not only to target content type itself but also to all its descendants.

In the list context the customization will appear if there is at least one content type covered by specified RegistrationId. Existing items in the list context are not analyzed – only content types of the list matter.

In the context of single list item the customization will appear only if the content type of current item is right.

Here is an example:
<CustomAction RegistrationType="ContentType" RegistrationId="0x0100A33D9AD9805788419BDAAC2CCB37509F">

"FileType"
For this type of registration RegistrationId must be an extension of the file for current list item. Because a file of current list item is analyzed this type of registration available in the context of single library item (i.e. item with file) only. The case is ignored and the leading dot is not needed before extension:
<CustomAction RegistrationType="FileType" RegistrationId="docx">

"ProgId"
For this type of registration RegistrationId must be an identifier of application where the content of the library item file created. SharePoint extracts this application identifier from list item file and saves in system field with name "HTML_x0020_File_x0020_Type". So similar to FileType registration ProgId registration is available only in context of single library item. The case is not important.

Which files can be targeted? You can target files of XML or HTML based formats. An example of XML-based format is MS Word document saved as "Word XML-document". It contains ProgId in the beginning of the body in the following tag:
<?mso-application progid="Word.Document"?>
An example of HTML-based format is MS Word document saved as "HTML-page" – the ProgId in this case will be saved in such tag:
<meta name=ProgId content=Word.Document>
You can test if SharePoint could extract ProgId from the given file by getting it from list item programmatically:
string ProgID = (string)listItem[SPBuiltInFieldId.HTML_x0020_File_x0020_Type];
or
string ProgID = (string)listItem["HTML_x0020_File_x0020_Type"];
Then you can use obtained value in your customization:
<CustomAction RegistrationType="ProgId" RegistrationId="Word.Document">





Workflow status codes (used for view filter) of SharePoint

Here is the list of the status codes used to maintain the workflow statuses. This list might be useful when anyone creates a view based on workflow status. If you are creating a view for a list filtered by the workflow status, you would need use the number rather than the words (e.g. 2 instead of In Progress, 4 instead of Cancelled etc)

Status
Value
Not Started 0
Failed on Start 1
In Progress 2
Error Occurred 3
Canceled 4
Completed 5
Failed on Start (retrying) 6
Error Occurred (retrying) 7
Canceled 15
Approved 16
Rejected 17

 



how to setup Document Library template via code in SharePoint

Here is simple example how to setup Document Library template via code:

using (SPSite site = new SPSite("http://mycoolsite")) { 
     using (SPWeb web = site.OpenWeb()) 
     { 
          SPList list = web.Lists["MyLibrary"]; 
          SPDocumentLibrary docLib = (SPDocumentLibrary) list; 
          docLib.DocumentTemplateUrl = "/mylibrary/Forms/NewTemplate.doc"; 
          docLib.Update(); 
     } } 
However, if template is outside Document Library Forms folder you will receive error:
Invalid template URL.
The template must exist in the Forms directory of this document library. Create the template in the Forms directory, and then re-type the Web address. Note that you cannot move or copy a template into the Forms directory.
You can provide document template to forms folder of Document Library via feature using module element. Your feature element.xml would look something like this:
<?xml version="1.0" encoding="utf-8" ?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 
    <Module  
        Name="MyLibrary" SetupPath="Features\MyLibrary" 
        Path="" Url="_cts/MyLibrary"> 
        <File Url="NewTemplate.doc" /> 
    </Module> </Elements> 
IMO this is not right solution for you. I suggest that you deploy custom content type already associated to custom template and when you create new library you just add content type to it. There are plenty articles on web covering this. Here are few (found by simple google search) to get you started:
Or you can use custom document templates (as you pointed in your question):

Supply a doc template for a Content Type in a Feature in SharePoint

So if you have played with MOSS features at all, you probably know that it is possible to deploy all kinds of customizations as features: custom actions, workflows, list definitions, content types, etc. In my demo, I wanted a feature that contained a content type for a document library to also provide a new word document "InterviewConfirmation.docx" as its template. Surprisingly, this little extra is a bit hard to find. You can easily find how to declare the content type, how to add site columns to it, and how to bind it to a list. But supply a document template. Nope. Nada. So here is a nice piece of info:
First in the feature.xml file, you need to include your element manifest where the content type is stored. And you also need an elementfile declaration for the document template:
<ElementManifests>
    <ElementManifest Location="hrdocs.xml"/>
    <ElementFile Location="InterviewConfirmation.docx"/>
  </ElementManifests>
Then in the element manifest, the following declares a Interview Confirmation content type that derives from document (0x0101). You then use the content type's DocumentTemplate element to build the link to the file. But you need to use a module to get the file loaded into the site collection. After some exploring with SharePoint designer, you can see where these files go. They are stored in the _cts folder in a folder named the same as the content type. You can use a Module element to provision the file.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ContentType ID="0x01010D"
               Name="Interview Confirmation"
               Group="HR Docs"
               Description="Interview Confirmation"
               Version="0">
    <DocumentTemplate TargetName="InterviewConfirmation.docx"/>
  </ContentType>
  <Module Name="HRDocs" Url="_cts/Interview Confirmation" RootWebOnly="TRUE">
    <File Url="InterviewConfirmation.docx" Name="InterviewConfirmation.docx" Type="Ghostable"></File>
  </Module>
</Elements>

The difference between SPWeb.Users and SPWeb.SiteUsers in SharePoint

Getting lists of users is easy, when you know how. There are some subtle differences that might trip you up when you’re looking to retrieve a list of users from a SharePoint Site or Portal Area. The SPWeb class has two properties, Users and SiteUsers. Here’s the documentation on each:

SPWeb.UsersGets the collection of user objects belonging to the Web site.
SPWeb.SiteUsersGets the collection of all users belonging to the site collection.

There’s just a *slight* difference in wording here. After all, SPWeb.Users gives me the user objects of the web site right? Not really.
As this was something that was bugging me with a problem I had, I decided to do a small spike to prove (or disprove) what was going on. When you have a design problem or a technical complexity that has to be addressed (before staring your work to reduce the risk) you create a spike, a small side project apart from your current work. The spike solutions are developed to solve or explore critical problems. Ideally those programs will be thrown away once every developer gets a clear idea about the problem.
So we’ll create the SSWP[1] with the following RenderWebPart method defined:
   63         protected override void RenderWebPart(HtmlTextWriter output)
   64         {
   65             SPSite site = SPControl.GetContextSite(Context);
   66             SPWeb web = site.OpenWeb();
   67             output.Write(string.Format("<strong>Information</strong><br>User Count={0}, Current User ID={1}</p>",
   68                 web.Users.Count, web.CurrentUser.ID));
   69 
   70             StringBuilder sb = new StringBuilder();
   71             sb.Append("<table border=1>");
   72             sb.Append("<tr><td colspan=3><strong>SPWeb.Users</strong></td></tr>");
   73             sb.Append("<tr><td>ID</td><td>LoginName</td><td>Name</td></tr>");
   74             foreach (SPUser user in web.Users)
   75             {
   76                 sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>",
   77                     user.ID,
   78                     user.LoginName,
   79                     user.Name);
   80             }
   81             sb.Append("</table>");
   82             output.Write(sb.ToString());
   83 
   84             sb = new StringBuilder();
   85             sb.Append("<table border=1>");
   86             sb.Append("<tr><td colspan=3><strong>SPWeb.SiteUsers</strong></td></tr>");
   87             sb.Append("<tr><td>ID</td><td>LoginName</td><td>Name</td></tr>");
   88             foreach (SPUser user in web.SiteUsers)
   89             {
   90                 sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>",
   91                     user.ID,
   92                     user.LoginName,
   93                     user.Name);
   94             }
   95             sb.Append("</table>");
   96             output.Write(sb.ToString());
   97 
   98             try
   99             {
  100                 SPUser currentUser = web.SiteUsers.GetByID(web.CurrentUser.ID);
  101                 output.Write(string.Format("</p>Current user is {0} (ID={1})",
  102                     currentUser.LoginName, currentUser.ID));
  103             }
  104             catch(SPException e)
  105             {
  106                 output.Write(string.Format("</p>Error getting user ({0})", e.Message));
  107             }
  108         }
So what’s this thing doing? Not much but basically:
  • Get a reference to the SPSite object using the GetContextSite method of SPControl
  • Open the SPWeb object using the OpenWeb method of the SPSite
  • Write out some information about the number of users and current user id
  • Create a small table with the id, login name, and display name of each user in the SPWeb.Users collection
  • Do the same thing but with the SPWeb.SiteUsers collection
  • Retrieve the SPUser object from the Web using the GetByID method and display information about that user
It’s the last part (wrapped in a try/catch block) that you should pay attention to.
Here’s the output of the Web Part logging in as LOCALMACHINE\Administrator when displayed in a SharePoint Portal Server Area:

And here’s the same Web Part when displayed in a Windows SharePoint Server site:

When you create an area or site, several users are automatically added behind the scenes. In the case of an area on the portal, you’ll see that SiteUsers contains more names than what’s in the WSS site. It adds in a “BUILTIN\Users” domain group (ID 4) and adds the “NT AUTHORITY\Authenticated Users” at the end (ID 6) in an area. In a site, “NT AUTHORITY\Authenticated Users” takes up the #4 slot, and the “BUILTIN\Users” is nowhere to be found.
Also when you create a site, it adds the creator (in this case “Administrator”) to the list of users (go into Site Settings | Manage Users to see the list). In area, the creator of that area shows up in the SPWeb.Users list, but it’s not present on the “Manage Security” page.
Here’s a rundown on the user ID slots that are filled in automatically:

IDDescription
1User who created the site or area
2Not sure on this one? Sorry.
3Application Pool Id, crawler account.
4BUILTIN\Users on Portal, NT AUTHORITY\Authenticated Users on WSS
5Additional individual users you add to the site, or any new users who happen along.
6NT AUTHORITY\Authenticated Users on Portal only, otherwise the next user you add or visits the area.


Note: these values are from most setups I’ve done, the way you configure your portal (turning on anonymous for example) might change these values somewhat so use them as a guideline, not a set of stone tablets that someone hands down to you after taking a siesta in the mountains.
You might say, “But Bil, I really only want the current user so SPWeb.CurrentUser should be good enough right?”. Maybe. What if you want to retrieve a user by ID (that might be stored somewhere else, but corresponds to the same ID # in the site). Or you want to display all the users in the site. This will become important when I blog later this week about Impersonation (everyone’s favorite topic).
So here’s the same Web Part, but being rendered by a regular Joe user (spsuser) who has read access to the site. He’s been added manually to the WSS site, but he’s a member of the Readers group at the Portal and doesn’t show up in the SPWeb.Users list. First, the Portal Area rendering:

Now the WSS site rendering:

Remember when I said to pay attention to that try/catch block? If you had used a bit of code like SPWeb.Users.GetByID (instead of using the SiteUsers property) you would have got an exception thrown while looking for a user with an ID of 5. As you can see in the SPWeb.Users list, it doesn’t exist because this will only display domain groups and indvidual users who have been manually added to the site (and Administrator got added automatically when the site got created).
Another thing that’s interesting is that if you did add “spsuser” to the site manually he would show up in the SPWeb.Users list above. However if you removed him, he would vanish from SPWeb.Users but he would still show up in the SPWeb.SiteUsers list. His ID # is reserved so the next user you added manually would have an ID of #6 (in the case of the site) and if you re-added “spsuser” at a later date, he would re-appear in both lists with an ID of #5.
So in a nutshell… if you’re going after a list of all users or want to retrieve a user from the list but he’s part of a group, then use the SiteUsers property instead of Users. Otherwise, he might not be there.
Okay, this post might have been a little confusing as we’re flipping around between Users and SiteUsers and all that but hopefully the code and images describe it for you. Let me know if you’re totally confused, otherwise… enjoy!
[1] Super-Simple-Web-Part: Just a web part where we hard code the values in the RenderWebPart method. Nothing fancy here. No Domain Objects. No DTOs. No Layers. Just write out some code.

How to use SharePoint properties to save values instead of web.config with sharepoint 2010/2007

I had two web parts in the same project but I wanted them to share settings. As my experience as an ASP.Net developer was pointing me to use the web.config file, instead I thought SharePoint must have something similar to this without me having to mess with the web.config file. After searching and posting on MSDN, I did finally find a solution that uses the properties of SharePoint Sites and Webs.
Below is a sample code that stores the Employee Profile Group in the web so two web parts and an InfoPath form can access the values.
The GetWebProperty function creates the property if it doesn't exist, and if it does it'll return the string value. It's important to call this function before setting a web property, especially the first time it's run so the property is created. I suppose you could technically put the same creation functionality in the SetWebProperty as well, but I was using Get (getting values into my webpart) before my Set (using edit pane to view it).
string employeeProfile = GetWebProperty("EmployeeProfileUserGroup");
SetWebProperty("EmployeeProfileUserGroup", pe.DisplayText);
static string GetWebProperty(string Name)
{
 using (SPSite site = new SPSite(SPContext.Current.Site.ID))
 {
  SPWeb web = site.OpenWeb(SPContext.Current.Web.ID);
  if (web.Properties[Name] == null)
  {
   web.AllowUnsafeUpdates = true;
   web.Properties.Add(Name, "");
   web.Properties.Update();
   web.AllowUnsafeUpdates = false;
   return "";
  }
  else
  {
   return web.Properties[Name].ToString();
  }
 }
}
void SetWebProperty(string Name, string Value)
{
 using (SPSite site = new SPSite(SPContext.Current.Site.ID))
 {
  SPWeb web = site.OpenWeb(SPContext.Current.Web.ID);
  GetWebProperty(Name); //ensure the property exists
  web.AllowUnsafeUpdates = true;
  web.Properties[Name] = Value;
  web.Properties.Update();
  web.AllowUnsafeUpdates = false;
 }
}
If you would like to share the same properties across multiple webs, use the Site.RootWeb object and store all properties there!

The difference between SPWeb.Users and SPWeb.SiteUsers of SharePoint

Getting lists of users is easy, when you know how. There are some subtle differences that might trip you up when you're looking to retrieve a list of users from a SharePoint Site or Portal Area. The SPWeb class has two properties, Users and SiteUsers. Here's the documentation on each:

SPWeb.Users Gets the collection of user objects belonging to the Web site.
SPWeb.SiteUsers Gets the collection of all users belonging to the site collection.

There's just a *slight* difference in wording here. After all, SPWeb.Users gives me the user objects of the web site right? Not really.

As this was something that was bugging me with a problem I had, I decided to do a small spike to prove (or disprove) what was going on. When you have a design problem or a technical complexity that has to be addressed (before staring your work to reduce the risk) you create a spike, a small side project apart from your current work. The spike solutions are developed to solve or explore critical problems. Ideally those programs will be thrown away once every developer gets a clear idea about the problem.

So we'll create the SSWP[1] with the following RenderWebPart method defined:

   63         protected override void RenderWebPart(HtmlTextWriter output)

   64         {

   65             SPSite site = SPControl.GetContextSite(Context);

   66             SPWeb web = site.OpenWeb();

   67             output.Write(string.Format("<strong>Information</strong><br>User Count={0}, Current User ID={1}</p>",

   68                 web.Users.Count, web.CurrentUser.ID));

   69 

   70             StringBuilder sb = new StringBuilder();

   71             sb.Append("<table border=1>");

   72             sb.Append("<tr><td colspan=3><strong>SPWeb.Users</strong></td></tr>");

   73             sb.Append("<tr><td>ID</td><td>LoginName</td><td>Name</td></tr>");

   74             foreach (SPUser user in web.Users)

   75             {

   76                 sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>",

   77                     user.ID,

   78                     user.LoginName,

   79                     user.Name);

   80             }

   81             sb.Append("</table>");

   82             output.Write(sb.ToString());

   83 

   84             sb = new StringBuilder();

   85             sb.Append("<table border=1>");

   86             sb.Append("<tr><td colspan=3><strong>SPWeb.SiteUsers</strong></td></tr>");

   87             sb.Append("<tr><td>ID</td><td>LoginName</td><td>Name</td></tr>");

   88             foreach (SPUser user in web.SiteUsers)

   89             {

   90                 sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>",

   91                     user.ID,

   92                     user.LoginName,

   93                     user.Name);

   94             }

   95             sb.Append("</table>");

   96             output.Write(sb.ToString());

   97 

   98             try

   99             {

  100                 SPUser currentUser = web.SiteUsers.GetByID(web.CurrentUser.ID);

  101                 output.Write(string.Format("</p>Current user is {0} (ID={1})",

  102                     currentUser.LoginName, currentUser.ID));

  103             }

  104             catch(SPException e)

  105             {

  106                 output.Write(string.Format("</p>Error getting user ({0})", e.Message));

  107             }

  108         }

So what's this thing doing? Not much but basically:

  • Get a reference to the SPSite object using the GetContextSite method of SPControl
  • Open the SPWeb object using the OpenWeb method of the SPSite
  • Write out some information about the number of users and current user id
  • Create a small table with the id, login name, and display name of each user in the SPWeb.Users collection
  • Do the same thing but with the SPWeb.SiteUsers collection
  • Retrieve the SPUser object from the Web using the GetByID method and display information about that user

It's the last part (wrapped in a try/catch block) that you should pay attention to.

Here's the output of the Web Part logging in as LOCALMACHINE\Administrator when displayed in a SharePoint Portal Server Area:

And here's the same Web Part when displayed in a Windows SharePoint Server site:

 

When you create an area or site, several users are automatically added behind the scenes. In the case of an area on the portal, you'll see that SiteUsers contains more names than what's in the WSS site. It adds in a "BUILTIN\Users" domain group (ID 4) and adds the "NT AUTHORITY\Authenticated Users" at the end (ID 6) in an area. In a site, "NT AUTHORITY\Authenticated Users" takes up the #4 slot, and the "BUILTIN\Users" is nowhere to be found.

Also when you create a site, it adds the creator (in this case "Administrator") to the list of users (go into Site Settings | Manage Users to see the list). In area, the creator of that area shows up in the SPWeb.Users list, but it's not present on the "Manage Security" page.

Here's a rundown on the user ID slots that are filled in automatically:

ID Description
1 User who created the site or area
2 Not sure on this one? Sorry.
3 Application Pool Id, crawler account.
4 BUILTIN\Users on Portal, NT AUTHORITY\Authenticated Users on WSS
5 Additional individual users you add to the site, or any new users who happen along.
6 NT AUTHORITY\Authenticated Users on Portal only, otherwise the next user you add or visits the area.

Note: these values are from most setups I've done, the way you configure your portal (turning on anonymous for example) might change these values somewhat so use them as a guideline, not a set of stone tablets that someone hands down to you after taking a siesta in the mountains.

You might say, "But Bil, I really only want the current user so SPWeb.CurrentUser should be good enough right?". Maybe. What if you want to retrieve a user by ID (that might be stored somewhere else, but corresponds to the same ID # in the site). Or you want to display all the users in the site. This will become important when I blog later this week about Impersonation (everyone's favorite topic).

So here's the same Web Part, but being rendered by a regular Joe user (spsuser) who has read access to the site. He's been added manually to the WSS site, but he's a member of the Readers group at the Portal and doesn't show up in the SPWeb.Users list. First, the Portal Area rendering:

Now the WSS site rendering:

Remember when I said to pay attention to that try/catch block? If you had used a bit of code like SPWeb.Users.GetByID (instead of using the SiteUsers property) you would have got an exception thrown while looking for a user with an ID of 5. As you can see in the SPWeb.Users list, it doesn't exist because this will only display domain groups and indvidual users who have been manually added to the site (and Administrator got added automatically when the site got created).

Another thing that's interesting is that if you did add "spsuser" to the site manually he would show up in the SPWeb.Users list above. However if you removed him, he would vanish from SPWeb.Users but he would still show up in the SPWeb.SiteUsers list. His ID # is reserved so the next user you added manually would have an ID of #6 (in the case of the site) and if you re-added "spsuser" at a later date, he would re-appear in both lists with an ID of #5.

So in a nutshell… if you're going after a list of all users or want to retrieve a user from the list but he's part of a group, then use the SiteUsers property instead of Users. Otherwise, he might not be there.

Okay, this post might have been a little confusing as we're flipping around between Users and SiteUsers and all that but hopefully the code and images describe it for you. Let me know if you're totally confused, otherwise… enjoy!

[1] Super-Simple-Web-Part: Just a web part where we hard code the values in the RenderWebPart method. Nothing fancy here. No Domain Objects. No DTOs. No Layers. Just write out some code. 



How to Configuration the User Profile Service in SharePoint 2010

Step by step guide in setting up the User Profile Service application, focusing on its configuration and administration and how we can enable the creation of user profiles via an Active Directory import .

SharePoint 2010 introduces the notion of "Service Applications" which build's upon the "Shared Services Provider (SSP)" which was introduced in SharePoint 2007.  Service Applications are individual services that can be configured independently and can be shared across other sites within your farm with some service applications that can also be configured across farms.

The individual service applications provided with SharePoint 2010 are listed as follows;

  • Access Services
  • Business Data Connectivity
  • Document Conversion
  • Excel Services
  • Managed Metadata Service
  • PerformancePoint
  • Search Service
  • Secure Store
  • State Service
  • Visio Graphics Service
  • User Profile Service

This article will build upon our initial SharePoint 2010 install utilizing the least privilege model which I have documented How to Install SharePoint 2010 using Least Privilege Service Accounts, so check it out if you haven't already done so.

Managed Metadata Service

The User Profile service requires that the Managed Metadata Service is setup and configured first before attempting setting up our first User Profile Service.  The Managed Metadata service allows you to utilize managed metadata and provides you with the ability to share content types across sites.  You can read more about Managed Metadata here.

To setup our Managed Metadata Service, navigate to Central Administration / Application Management / Manage Service Applications.

Click New and select "Managed Metadata Service"

Enter the follow details;

Name: Managed Metadata Service

Database Server: <server_name>

Database Name: Managed Metadata DB

I will utilize the sp_farm account for the Application Pool Identity.

Click Create.

Lastly, navigate to Central Administration / System Settings / Manage services on server and start the Managed Metadata Web Service.

User Profile Service

Now that we have successfully configured our Managed Metadata service we can now focus our attention on the User Profile Service.  The User Profile Service provides our SharePoint farm with all the social networking features that we have come to love in SharePoint 2007, plus more.  It forms the basis of My Site support, User profile pages, Audiences and some of the newer features in SharePoint 2010 social computing such as social tagging.

Before we begin, we need to ensure that our Farm account (DOMAIN\sp_farm) is listed as a member of the Local Administrator's group where the User Profile Synchronization (UPS) service will be deployed.  Please make a note to remove the DOMAIN\sp_farm account from the Local Administrator's group after provisioning the User Profile Synchronization service.  Please also note, that if you ever have to re-provision the UPS service at a later date, that you will need to ensure the DOMAIN\sp_farm account is added back to the Local Administrator's group.

Let's now navigate to Central Administration / Application Management / Manage Service Applications.

Click New and select "User Profile Service Application"

The "Create New User Profile Service Application" window pops up in which you will enter the following details; (you will obviously enter in the details based on your environment setup)

Name: User Profiles

Create new application pool: SharePoint – User Profiles

Register a new managed account: e.g. DOMAIN\sp_userprofiles (nb: this account will need to be provisioned in Active Directory first)

Enter your Profile Database server details and database authentication.  You will notice that SharePoint 2010 introduces the ability to configure Failover Server which allows you to associate your SharePoint databases with another SQL server for failover purposes utilising SQL Server database mirroring.   We will not specify a Failover Database server for any of our databases at this present time.

Specify your Synchronization Database which is used to store configuration and staging data for synchronization of profile data such as that from Active Directory.

Next, specify your Social Tagging Database which is used to store tags and notes that are created by users.  Social Tagging is a new feature in SharePoint 2010 which is not only displayed against the items that user's are tagging, but are also displayed in the user's activity feed.

Next, select your Profile Synchronization Instance Server.

In the proceeding section, we will not create a My Site Host URL and will leave this for part two of this series.

Click Create.

You should now have the User Profiles service application listed and  started.

We will now venture back into Central Administration / System Settings / Manage services on server.

Scroll down to the User Profile Service and User Profile Synchronisation Service and start both.  The User Profile Service should start without any further user interaction, however the User Profile Synchronization Service will ask for your SharePoint Farm credentials.

Click Ok.

Both services should now be listed as started.

This in turn, will correctly configure and start our ForeFront Identity Manager Windows Services (FIM).

At this point, it is imperative you run an IIS reset.  Even better, just reboot the machine

We will now configure our User Profile Connection to our Active Directory Domain.

Navigate to Central Administration / Application Management / Manage Service Applications.

Click on User Profiles / Manage.

Click on Configure Synchronizations connections / Create New Connection.

Enter the follow details;

Connection Name:

Type: Active Directory

Auto discover domain controller or specify a domain controller

Authentication Provider Type: Windows Authentication

Account Name / Password:

Port: 389

Click on Populate Containers

Click OK.

Your connection should now be listed as follows upon successful creation.

We can now easily setup connection filters against our Active Directory User Profile connection by clicking on the connection that was just created and selecting "Edit Connection Filters".

Specify and Add any User or Group exclusions and then click OK.

Next we will Configure a Synchronization Timer Job via Central Administration / Application Management / Manage Service Applications / User Profiles.

Click Enable

We will finish off by initiating a full synchronization via Central Administration / Application Management / Manage Service Applications / User Profiles / Start Profile Synchronization.

In order to confirm that the import was a success, the Number of User Profiles should now be set to the number of users in your organization, in my case I have 269 dummy users in my Active Directory domain.  Word of note; this will take some time and is considerably slower than an Active Directory User Profile import in SharePoint 2007.

You can also venture into Manage User Profiles and search for users (please take note that SharePoint 2010 does not display any users by default and that you will have to search for them).

Edit a User Profile to ensure that all the necessary Active Directory attributes were successfully imported.

We have now successfully completed a User Profile Synchronization which will form as a basis for User's My Sites in my next article.  Until then, happy SharePointing!!

References

User Profile Service administration (SharePoint Server 2010) http://technet.microsoft.com/en-us/library/ee721050.aspx

Configure profile synchronization (SharePoint Server 2010) http://technet.microsoft.com/en-us/library/ee721049.aspx

Related Posts



How to Configuration outgoing email in SharePoint 2010 with Exchange 2010 – Step by Step Guide

In my How to Configuration incoming email in SharePoint 2010 with Exchange – Step by Step Guide I provided you with a guide in setting up your SharePoint 2010 farm providing it with the capabilities in receiving incoming email which can then be delivered directly to your SharePoint libraries and or lists.  Today we wrap up our 2 part series on email flow in SharePoint 2010 in which I will provide you with another step by step guide in configuring your SharePoint Farm in order for it to send outgoing emails through your Microsoft Exchange server.

The environment

This article builds on the SharePoint Farm setup that I have documented here. It consists of the following servers which would form a common basis in most large organizations.

  • Windows 2008 R2 server running Active Directory Domain Services
  • Windows 2008 R2 server running SQL 2008 R2
  • Windows 2008 R2 server running SharePoint 2010 RTM
  • Windows 2008 R2 server running Exchange 2010 RTM
  • Windows 7 client running Office 2010 RTM

SharePoint 2010 allows you to configure any SMTP service including the one which I had setup in my previous article to send outgoing email, however we will utilise Exchange 2010 (same instructions apply for Exchange 2007) to provide email delivery to our end users.  Instructions on configuring the SMTP service (i.e. you are not using Microsoft Exchange in your environment) can be found on TechNet.

Creating a Receive Connector in Exchange 2010 

If you recall from my previous article  How to Configuration incoming email in SharePoint 2010 with Exchange – Step by Step Guide, we created a "Send Connector" in Exchange to forward the messages to the SMTP service that we had configured and installed.  This time round we will create a "Receive Connector" in Exchange 2010.

Launch the Exchange Management Console and navigate to Server Configuration / Hub Transport / New Receive Connector.  The New Receive Connector wizard is invoked.

Enter a descriptive name and ensure "Custom" is selected as the intended use.

Click Next

Leave "All Available IPv4" in your Local Network settings unless you have specific Exchange IP requirements.

Click Next

Edit the IP address of your SharePoint 2010 server.

Click Next

Click New

You will now notice that our SharePoint 2010 Outgoing mail connector is listed with our default Exchange 2010 Receive Connectors..

We will now venture into its properties and make a minor permission change.  Click on the "Permission Groups" tab and select Anonymous users.

Click Apply.

Configuring outgoing email in SharePoint 2010 Central Administration

Launch Central Administration and navigate to System Settings / E-Mail and Test Messages / Configure outgoing e-mail settings.

Enter your Outbound SMTP server, i.e. your Exchange server where we created our receive connector and specify a From and Reply-to address.

Click OK

Testing our configuration

Lets navigate to our SharePoint 2010 web application and create an Alert .  In my example I will create an immediate alert for Announcements.

Navigate to your Announcement List and click on List Tools/List and then click on "Alert Me" located in the ribbon interface.

Select "Set alert on this list" and select your Alert options.  Ensure that you have "send notifications immediately" selected for testing purposes.

Click OK

You should receive your notification email that you have successfully subscribed soon after creating your alert.

I will now create a Test Announcement to ensure that the actual alert is delivered.

Alas! 5 minutes later (based on the immediate timer job definition schedule) we have received our email alert confirming that our SharePoint configuration with Exchange was successful.

Did you know that you can also configure outgoing email for a specific Web application?  You might want to do this if you have multiple SharePoint Web Applications hosting specific site collections and would want a different From and or Reply Address setup.

Even though we are now going to configure outgoing email for a specific Web application, you are still required to setup the default farm outgoing email settings as per the above.

Configuring outgoing email for a specific Web application in SharePoint 2010 Central Administration

Launch Central Administration / Application Management / Manage Web Applications.

Select one of your Web Applications and then select "General Settings" from the Ribbon.

Select "Outgoing E-Mail" from the drop down.

It will pick up your default farm settings that we entered in earlier in which you can now change the From and Reply-to address to something more specific for the selected Web application.

Click OK

We are done!  I hope you have found this step by step guide in configuring outgoing email in SharePoint 2010 with Exchange useful, and stay tuned as we continue our journey in configuring our SharePoint 2010 Farm.

Articles in this series 

 

Related Posts