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!