Tuesday, August 10, 2010

SharePoint 2010: Client Object Model for JavaScript (ECMAScript)

Copyright from: Sohel_Rana
As I said in my first post on Client Object Model (OM), there are three sets of Client OM: Managed .net client, Silverlight and ECMAScript. Lately I have posted an article on how to use Client OM from Managed .Net Client.Today I’ll go through Client OM for JavaScript.  ECMAScript Client OM is SharePoint 2010 client object model extension for using with JavaScript or JScript. Few points to notice about ECMAScript Client OM:
  • ECMAScript object model can only be used in SharePoint sites. So you can’t use this object model in an asp.net site to access SharePoint resources deployed in another url as this is cross-site scripting and not allowed.
  • You can’t use this object model in a SharePoint site to access resources in different SharePoint sites(i.e., different urls). For example, from mysite.mysp.com you can access resources in yoursite.yoursp.com using ECMAScript client OM. This is also cross-site scripting.
  • You can use JQuery with ECMAScript Client OM and for this you don’t need to do some extra work. All you need to do to use JQuery is to add reference to JQuery.js file and start using JQuery.
  • You can use this ECMAScript Client OM in web part pages or application pages (aspx pages) by referencing a javascript file (SP.js). You don’t need to add reference to the file manually rather use . The file is located on the path “Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS”
  • To update with JavaScript, you need to add a FormDigest tag in your page for security purpose. I’ll explain it later in details.

Use ECMAScript Library

At first use Visual Studio 2010 to create a SharePoint web part project. As a result, VS2010 will open a ascx control for you on the designer. 

1. Add reference to js file:

To use Client OM, add an entry like below in your web part ascx control. For your information, there’s an debug version of the sp.js called sp.debug.js which you can use for debugging but should not be used in production.
Collapse
<SharePoint:ScriptLink Name="SP.js" runat="server" OnDemand="true" 
    Localizable="false" />
Here, OnDemand means whether the sp.js file need to be loaded on demand (not in page load) or not.

2. Add FormDigest tag:

If your code modifies SharePoint content add a FormDigest control inside your page. The FormDigest add a security token inside your page based on user, site and time. Once the page is posted back the security token is validated. Once the security token is generated it’s valid for a configurable amount of time. Add the FormDigest inside
tag, as shown below:
Collapse
<SharePoint:FormDigest runat="server" />
For more information on FormDigest follow the links below:

3. Use Client OM to retrieve data:

Now you can use SharePoint ECMAScript library. Lets dissect the code snippet below. The first thing in using this library is that you need to get the ClientContext (just like SPContext). Then the context.get_web returns the current web (just like SPContext.Current.Web). Then client context’s load method is invoked passing the web object. Then the executequery method is invoked asynchronously passing two functions: onSuccess and OnFailed which will be called on success and fail correspondingly.
Collapse
<script type="text/javascript">
    function getWebProperties() {
        var ctx = new SP.ClientContext.get_current();
        this.web = ctx.get_web();
        ctx.load(this.web);
        ctx.executeQueryAsync(Function.createDelegate(this, this.onSuccess),
            Function.createDelegate(this, this.onFail));
    }
    function onSuccess(sender, args) {
        alert('web title:' + this.web.get_title() + '\n ID:' + this.web.get_id() +             '\n Created Date:' + this.web.get_created());    }
    function onFail(sender, args) {
        alert('failed to get list. Error:'+args.get_message());    }
script>
By calling getWebProperties method from any web part, you can get the current web’s title, id and creation date.

4. Load minimal data you need:

In the above code snippet, the Ctx.load method is invoked with only one parameter (web). The load method will load all properties of the web object. But we are only using Id, Title and Created Date properties. If you know which properties you are interested in, you can pass the properties names in the load method and only those properties will be loaded. For example the following load method will return only ID, Title and Created Date.
Collapse
ctx.load(this.web,'Title','Id','Created');
Remember, here the properties names are properties of SPWeb. You need to pass Title instead of title. The properties name uses CAML casing. You can get the full lists of ECMAScript namespaces, object, properties following the link on MSDN. The document is not final yet and may be changed. You can also look into the sp.debug.js file in the folder “Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS”, to get an idea of objects, properties and methods of ECMAScript Client OM.

5. Execute your JavaScript function after sp.js is loaded:

Sometimes you may need to execute your JavaScript (that uses ECMAScript Client OM) on page load in the browser. But since your JavaScript is using sp.js file and if the sp.js file is not loaded yet (since to lazy loading nature of sp.js), when your custom JavaScript will be executing, you’ll get your JavaScript function not executed. In this case you need to make sure your JavaScript code runs after sp.js finishes loading. You can do so by putting your JavaScript method call inside a js function as shown below:
Collapse
ExecuteOrDelayUntilScriptLoaded(myjsfucntion, "sp.js");
Putting your JavaScript function (i.e., myjsfunction) inside the ExecuteOrDelyUntilScriptLoaded method delays your method call until the sp.js file is loaded.

6. Update with ECMAScript Library:

You can use the Client OM to update SharePoint contents. The following code snippet shows how to update web title.
Collapse
<script type="text/javascript">
    function updateTitle() {
        var ctx = new SP.ClientContext.get_current();
        this.web = ctx.get_web();
        web.set_title('UpdatedTitle');        this.web.update();
        ctx.executeQueryAsync(Function.createDelegate(this, this.onUpdate),
            Function.createDelegate(this, this.onFail));
    }
    function onUpdate(sender, args) {
        alert('title updated');    }
    function onFail(sender, args) {
        alert('failed to update title. Error:'+args.get_message());    }
script>
By calling the updateTitle method from any web part or SharePoint application pages, you can change the title of current web site (where the web part or application page is deployed). For your information, in ECMAScript Client OM, to get an property use get_propertyName and to set a property use set_propertyName. To update list with ECMAScript library you need to add FormDigest tag.

Use JQuery with ECMAScript

You can use JQuery with ECMAScript without any conflict. As usual, you need to add jquery.js file reference to your page/web part or in master page. Then you can use JQuery as like normal asp.net applications. But make sure that if you need to execute any JavaScript function on page load event, you put this inside ExecuteOrDelayUntilScriptLoaded function.

Deployment Consideration

SharePoint provides two sets of JavaScript file: minified and unminified/debug version. For example sp.js file is minified and sp.debug is minified and debug version. The default master page in SharePoint has a scriptmanager in the page and whose ScriptMode is set to auto, as a result the minified version of js file loaded. If you want to use debug version you can add the in the section of the web.config. In the production you need to remove this entry to make sure minified version is used. The ECMAScript supported in the following browsers:
  • Microsoft Internet Explorer 7.0 or greater.
  • Firefox 3.5 or greater
  • Safari 4.0 or greater

More Information

To get the full list of namespaces and Classes, you can download the SharePoint 2010 SDK or you can follow the link on MSDN.

SharePoint 2010: Client Object Model – an Introduction

Copyright from: Sohel's Blog

SharePoint 2007 allows using its Object model to run against server running SharePoint. For clients (not running SharePoint in the box) the simplest way to communicate with SharePoint server is web services. SharePoint Client Object Model (OM) can be run on client PC (where SharePoint is not installed) to communicate with SharePoint server. So whereas SharePoint (Server) Object Model runs in a SharePoint server and can manipulate SharePoint objects, Client OM can run in client PC and communicate with SharePoint server remotely.
SharePoint 2010 introduces three new client APIs which can be used to interact with SharePoint sites. The three APIs are targeted for three different types of clients:
1. For .net Managed applications (for example, console applications, window applications, web applications etc, which are not running inside SharePoint Context).
2. For Silverlight applications.
3. For using with JavaScript (called ECMAScript). This API is only available for applications hosted inside SharePoint (for example, web part deployed in SharePoint site can use this JavaScript API for accessing SharePoint from browser using JavaScript).
I’ll explain all of these API sets gradually. In this post I’ll explain some basic problems SharePoint developers faced during development with SharePoint 2007 in absence of Client Object Model.

Why Client Object Model (OM)?

SharePoint 2007 had no Client Object model available. So you may ask why this is introduced in SharePoint 2010? We had no problem without Client OM and millions of sites are running smoothly without having Client OM. The main reason is that Microsoft has found lot of requests from SharePoint users to introduce more and more web services to get data out of SharePoint in the last couple of years. But introducing web services will not fix the issues, as Microsoft found, because then the request for more functionality in the web services will continue. Even if Microsoft provides a good numbers of web services with SharePoint, customization in web services will be required for different clients and this will make the out of the box web services unusable. Also introducing a large number of web services will be a waste as not all companies will use all the web services functionalities.
In response to add more web services from users, Microsoft has taken a different approach called Client Object Model (OM). This SharePoint Client OM will allow getting data out of SharePoint from PCs that are not hosting SharePoint. Also Client OM provides complete API to interact with SharePoint Server which is more intuitive and useful and very much similar with SharePoint Object Model.

Similarity with SharePoint Object Model

Now SharePoint developers will fear that the Client Object Model will introduce new burden for them to get used to it. But SharePoint team provided great efforts to keep the Client OM familiar with SharePoint Object Model. The following table shows the equivalent objects in Client and SharePoint Object Model.
Server (Microsoft.SharePoint)
Client Object Model
SPContext
ClientContext
SPSite
Site
SPWeb
Web
SPList
List
SPListItem
ListItem
SPField
Field
So the class names in Client OM are similar as like SharePoint Object Model. However the way client OM will be used a bit different than usual SharePoint Object Model that we will explore in the upcoming posts.

How Client OM is developed and work under the hood?

It’s interesting how SharePoint team has developed the same set of classes for three different sets of applications (Managed, Silverlight and ECMAScript). There is same class ListItem for three different set of applications. As shown in the following table, three different assemblies/files are used for three different types of applications.
Client Type
Assembly/File
Managed Client
Microsoft.SharePoint.Client
Silverlight
Microsoft.SharePoint.Client.Silverlight
ECMAScript
SP.js
To ensure the same class object (say ListItem) behaves similarly in three different types of applications SharePoint team followed the steps described below:
a) SharePoint team first set attributes to the SharePoint classes and methods and properties that need to be exposed in Client OM.
b) Then a code generator is run against the SharePoint object model to generate client OM automatically.
This automated code generation has ensured maximum compatibility between these three sets of APIs. As the following figure shows client communicate to the server thorough Client OM which under the hood uses Client.svc WCF service to communicate with SharePoint Server. Client.svc service uses Server OM as per client request and return result to the client in JSON format.


image
Figure: How Client Object model works with Server
With this new Client OM, we almost don’t need to use web service to communicate with SharePoint server. However, the client OM just released and we will find its shortcomings as well use it more and more in live projects. In my next posts I’ll go through three differents kinds of Client OM (Managed .net, Silverlight and ECMAScript).

Tuesday, August 3, 2010

Editing contents of a WSP (SharePoint)

  1. Rename the WSP to CAB
  2. Extract all contents to a folder – using Windows Explorer, or WinZip, WinRAR, or whatever
  3. Change the items you want, ie. MANIFEST.XML and remove a DLL (in my case)
  4. Create a new CAB file with the updated contents, using IZARC 
  5. Rename the newly created CAB to WSP
  6. Install to SharePoint 
PS: using IZARC
  1. Open IZArc as a ‘program’
  2. Create a new archive
  3. Choose a CAB file type
  4. Add the files – and check the box for “subfolders”

Monday, August 2, 2010

Referencing Javascript Files with SharePoint 2010 Custom Actions using SciptSrc

copy right from: Jan Tielens' Bloggings
If you’re an avid reader of this blog, you are probably aware of the fact that using Javascript plus SharePoint is a very powerful combination. In SharePoint 2007 there were a couple of techniques you could use to make sure your Javascript files would be referenced by SharePoint pages:
  1. Add the Script reference to the Master Page
  2. Use a Delegate Control (e.g. the AdditionalPageHead)
  3. Dynamically through code, e.g. in a Web Part
Although all those techniques work, and will still work in SharePoint 2010, they all have some limitations. The first technique requires you to build a custom Master Page, which may be a little overkill just to get a Javascript file referenced. Additionally, your custom Master Page is not used on Application Pages (unless you use the Superbranding trick). The second is my favorite one in SharePoint 2007, but the requirement is that the Master Page you’re using has the corresponding Delegate Control, and you need to have either a Server Control or Web User Control that generates HTML to reference the script. The third technique is nice if you only want to use the script when the Web Part is on the page, otherwise you’ll have to put the Web Part on every page where you’d like to reference the script.
SharePoint 2010 is adding another very interesting technique to this list; using the ScriptSrc attribute of the CustomAction element in a Feature. Check the following Feature Elements file:
http://schemas.microsoft.com/sharepoint/">
 
      ScriptSrc="
JSDemo/jquery-1.4.2.js"
      Location="ScriptLink"
      Sequence="100"
      >
 
 
The first important thing to notice is that the CustomAction element contains the ScrptSrc attribute that points in this example to the jQuery Javascript library. The jQuery library is added to the /_layouts folder in the SharePoint Root, in a folder called JSDemo (the /_layouts/ prefix is added automatically). By the way, adding files to the /_layouts folder is very easy in a SharePoint project in Visual Studio 2010, using a Mapped Folder.  The second important attribute is the Location; it must be set to ScriptLink so the Javascript file is referenced in the head element of the page. Optionally you can specify a Sequence attribute to determine the in which order the script references will be added (if you have multiple). When Feature is activated, it results in the following HTML:
document.write('

Tuesday, July 20, 2010

A Quicker Way to Create Custom SharePoint List Templates

Ever tried to create a custom list template for a SharePoint 3.0-based site? Something you thought was likely to be not such a big task quickly turned in to a nightmare of XML and GUIDs, right? Creating custom list templates is not a trivial task... nor is it a terribly good story. It's pretty darn complicated and can be quite an undertaking. In fact, last year when Rob Bogue, Paul Andrew and I were coming up with the content ideas and reviewing the labs/webcasts for the Introduction to SharePoint for ASP.NET Developers campaign, one thing Rob and I were adamant about was zero coverage of list definitions/templates and site definitions/templates. Why? The goal was to bring ASP2 developers to the platform... not send them running away! These things are nasty and scary… avoid them at all costs… unless if you simplify things…
Most people I know stay away from list definitions... and I did for a while. But now I’m not so scared of them… I came up with an approach that simplifies things. My approach to building them really makes things simpler and easier. This follows the same theme I have for site definitions which I blogged about earlier last year. My take on site definitions can be boiled down to the following:
  • Copy Blank Site and give it a new name/ID... this is just a shell... nothing special in it (I like to remove the WSS 3.0 logo from the default page so it really is a Blank Site, not a Not So Blank Site).
  • Create Features and associated stapling Features, stapling to the new site def.
  • Now you have a site def you can change after creating sites with it (by activating/deactivating stapling Features) and it's easier to build in a modular fashion.
The point of this post is demonstrate how to create list definitions quickly without much hassle. Scared of schema.xml? Don't be... just ignore 95% of it! A few quick edits taking less than 2 minutes and you're good! OK... here it goes...
  1. Create content type(s) - I don't like adding columns to lists... I use content types for everything... and I mean EVERYTHING. Even if it is going to be used in just one list, I still use content types. Create these guys in a Feature for the most portability and reuse.
  2. Create list template in Feature element manifest - Nothing special here... your typical node like the following:
    ListTemplate1
  3. Create the list template’s schema - Now for the nasty part everyone tries to avoid. Create a subfolder in your Feature with the name of the list. Now you need the list schema… here is where you are going to cheat and save time! Copy the schema.xml file from the OOTB Custom List template found in the Feature CustomList. Put that schema.xml file in your Feature, within the folder you just created.
    ListProject1
    Why use the schema.xml file from CustomList? Great question: because it is the most bare bones schema file out there… it has the absolute minimum stuff in it (ie: fields, content types & views) you need to implement a list. I like starting from it and making a few tweaks.
  4. Update list schema.xml – The worst part about creating custom list definitions is the schema.xml file. But, if you start from a template, ala CustomList, it’s much easier. Now… make the following edits to schema.xml:
    1. Change the list schema’s metadata – set the title of the list and it’s URL:

      ListSchema1
    2. Add & remove content types – remove all the existing content types listed in the schema and add back just the one(s) you created previously:

      ListSchema2
    3. Add the fields that will be in the list – next, you need to add all the fields that will be in the list… include all the fields on all the content types. Make sure to leave the two LinkTitle and LinkTitleNoMenu alone… those are the special ones we get in lists that hyperlink the list item to get the ECB menu or a link to the list item’s display page:

      ListSchema3
    4. Modify the node for the two default views – for the two default views, search for the node and add all the fields that should be shown in that view:

      ListSchema4
    But wait, what about those other views you want in your list? If you want to create them, go for it… but you do see all that CAML right? Forget it for now… I’ll come back to that topic…
  5. Now you can deploy it, but when testing I like to create an instance of the list template in the Feature deploying it (you can always remove it before deploying to production). There’s just one little trick when you create an instance of a list and you’re using content types, you need to do two things:
    1. First, you need to bind the content type to the list instance like this:

      ListInstance
    2. Second, you need to configure the list to enable the use of content types. Unfortunately you have to do this through the API as the Feature schema doesn’t provide this option. Best pace for this: in your FeatureActivated receiver method:

      FeatureReceiver
So now you’ve got a brand new custom list template in just mere minutes! But what if you want to have some custom list views? This isn’t so bad… instead of creating them from scratch, use an IDE: the browser! After creating the view using the browser, use a tool like SharePoint Manager 2007 to get the source of the view and manually add it back into your schema.xml file.
SPManager
Now, to test your view by deleting all instances of the test list, deactivate the Feature and uninstall it… remove all instances of it. Now, try it again. Using this process I’ve been able to create list templates complete with two or three complex views in less than 15 or 20 minutes. Not so bad eh?

Monday, July 19, 2010

Impersonation .Net

1) What is Imperonation?
- Impersonation is the process of assigning a user account to an unknown user.By default, the anonymous access account is named IUSER_machinename. This account can be use to control anonymous users' access to resources on the server. This mechanism allows a server process to run using the security credentials of the client. When the server is impersonating the client, any operations performed by the server are performed using the client's credentials. Impersonation does not allow the server to access remote resources on behalf of the client.






2) How to implement impersonation in an ASP.NET application:

This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System.Web.Security
  • System.Security.Principal
  • System.Runtime.InteropServices
If you want to impersonate a user on a thread in ASP.NET, you can use one of the following methods, based on your requirments:



Note: You can use the following code to determine what user the thread is executing as:

System.Security.Principal.WindowsIdentity.GetCurrent().Name

2.1) 



Impersonate the IIS Authenticated Account or User








- To impersonate the Microsoft Internet Information Services (IIS) authenticating user on every request for every page in an ASP.NET application, you must include an tag in the Web.config file of this application and set the impersonate attribute to true. For example:


2.2) Impersonate a Specific User for All the Requests of an ASP.NET Application

 - To impersonate a specific user for all the requests on all pages of an ASP.NET application, you can specify the userName and password attributes in the tag of the Web.config file for that application. For example:


Note The identity of the process that impersonates a specific user on a thread must have the "Act as part of the operating system" privilege. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. This information applies only to the .NET Framework 1.0. This privilege is not required for the .NET Framework 1.1.

To work around this problem, use one of the following methods:




  • Grant the "Act as part of the operating system" privilege to the ASPNET account (the least privileged account).Note Although you can use this method to work around the problem, Microsoft does not recommend this method.
  • Change the account that the Aspnet_wp.exe process runs under to the System account in the configuration section of the Machine.config file.
2.3) Impersonate the Authenticating User in Code
- To impersonate the authenticating user (User.Identity) only when you run a particular section of code, you can use the code to follow. This method requires that the authenticating user identity is of type WindowsIdentity.
For example: 
VS C#:  
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

2.4) Impersonate a Specific User in Code
To impersonate a specific user only when you run a particular section of code, use the following code:






using System.Web
using System.Web.Security 
using System.Security.Principal
using System.Runtime.InteropServices


public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;


WindowsImpersonationContext impersonationContext; 


[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, 
String lpszDomain,
String lpszPassword,
int dwLogonType, 
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken, 
int impersonationLevel,  
ref IntPtr hNewToken);
                          
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();


[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern  bool CloseHandle(IntPtr handle);


public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("username", "domain", "password"))
{
//Insert your code that runs under the security context of a specific user here.
undoImpersonation();
}
else
{
//Your impersonation failed. Therefore, include a fail-safe mechanism here.
}
}


private bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;


if(RevertToSelf())
{
if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}

}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}


private void undoImpersonation()
{
impersonationContext.Undo();
}








Note The identity of the process that impersonates a specific user on a thread must have the "Act as part of the operating system" privilege if the Aspnet_wp.exe process is running on a Microsoft Windows 2000-based computer. The "Act as part of the operating system" privilege is not required if the Aspnet_wp.exe process is running on a Windows XP-based computer or on a Windows Server 2003-based computer. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. .

To work around this problem, use one of the following methods:




  • Grant the "Act as part of the operating system" privilege to the ASPNET account.Note We do not recommend this method to work around the problem.
  • Change the account that the Aspnet_wp.exe process runs under to the System account in the configuration section of the Machine.config file.

Sunday, July 18, 2010

LUHN Algorithm in C# and LINQ

(Copyright from: Just Agile.com)
The LUHN algorithm is commonly used in credit card verification schemes on e-commerce websites. It provides a simple means of verifying that a user has entered their credit card number correctly.
The LUHN algorithm works by taking a series of digits and applying a checksum. The digits are valid if the checksum modulo 10 is equal to 0.
The checksum is calculated as follows: assuming each digit is indexed from right to left: D(N)D(N - 1)...D(4)D(3)D(2)D(1), then compute the sum D(1) + 2 x D(2) + D(3) + 2 x D(4) + D(5) + 2 x D(6) + etc. Basically, every even digit in the sum is doubled. The remainder of the sum after dividing by 10 gives the final value of the checksum.

LUHN Checksum

It's a great example of LINQ and I don't think you'll find a more concise implementation anywhere else (one line if you remove the formatting, and it handles removing white space)!
public static int ComputeChecksum(string value)
{
    return value
        .Where(c => Char.IsDigit(c))
        .Reverse()
        .SelectMany((c, i) => ((c - '0') << (i & 1)).ToString())
        .Sum(c => c - '0') % 10;
}
To validate based on the checksum:
public static bool IsValid(string value)
{
   return ComputeChecksum(value) == 0;
}
This example uses the following namespaces:
using System;
using System.Collections.Generic;
using System.Linq;

Notes

Wikipedia states that some credit card companies allow 5 as well as 0 to be valid values for the checksum, however, I've never come accross this scenario in the UK, so let me know if you have!

Tuesday, July 6, 2010

Render Pattern not working in SharePoint 2010

SharePoint 2010 uses an XSLT rendering system for displaying field values in list views. If you have custom field types that use the construct for modifying the display value of a field in SharePoint 2007 you will find this no longer works. But backwards compatability saves the day, just add TRUE into your field type declaration and the XSLT rendering will be ignored and legacy CAML rendering will take its place.

XSLT rendering is still used to render the field value, but the value is first transformed using the CAML render pattern before being passed into the XSLT

Image

Thursday, July 1, 2010

Convert List/IEnumerable to DataTable/DataView

Here’s a method to convert a generic List to a DataTable. This can be used with ObjectDataSource so you get automatic sorting, etc.
01///
02/// Convert a List{T} to a DataTable.
03///
04private DataTable ToDataTable(List items)
05{
06    var tb = new DataTable(typeof (T).Name);
07 
08    PropertyInfo[] props = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
09 
10    foreach (PropertyInfo prop in props)
11    {
12        Type t = GetCoreType(prop.PropertyType);
13        tb.Columns.Add(prop.Name, t);
14    }
15 
16    foreach (T item in items)
17    {
18        var values = new object[props.Length];
19 
20        for (int i = 0; i < props.Length; i++)
21        {
22            values[i] = props[i].GetValue(item, null);
23        }
24 
25        tb.Rows.Add(values);
26    }22/
27 
28    return tb;
29}
30 
31///
32/// Determine of specified type is nullable
33///
34public static bool IsNullable(Type t)
35{
36    return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
37}
38 
39///
40/// Return underlying type if type is Nullable otherwise return the type
41///
42public static Type GetCoreType(Type t)
43{
44    if (t != null && IsNullable(t))
45    {
46        if (!t.IsValueType)
47        {
48            return t;
49        }
50        else
51        {
52            return Nullable.GetUnderlyingType(t);
53        }
54    }
55    else
56    {
57        return t;
58    }
59}

Wednesday, May 5, 2010

What you need to know about AllowUnsafeUpdates (Part 2)

In short here is how to deal with AllowUnsafeUpdates:
1) Don’t update SharePoint objects from your code behind on GET requests as if you do so your code will be exploitable via a cross-site scripting. If you understand the consequences of doing this and still want to do it then see the first part of this article about how to use the AllowUnsafeUpdates property.
2) If your code is processing a POST request then make sure you call SPUtility.ValidateFormDigest() before you do anything else. This will ensure that the post request is validated (that it is not a cross-site scripting attack) and after that you will not have to worry about AllowUnsafeUpdates, because its default value will be “true” after the form digest is validated. To find out more about this read below.
So you have probably noticed from part one of the article that the internal method that sets the AllowUnsafeUpdates property had quite an interesting name: SetIgnoreCanary(). Canary is something that refers to a method of protecting from stack overflow attacks. The terminology is a reference to the historic practice of using canaries in coal mines, since they would be affected by toxic gases earlier than the miners, thus providing a biological warning system. In SharePoint the request canary is a unique pseudo-random value that protects you from cross-site scripting attacks. If you have ever examined the HTML source of your SharePoint pages you have probably noticed the __REQUESTDIGEST  hidden field.  This is what is referred to as the canary or the Form Digest and is used to verify that the request is genuine.
<input
    type=”hidden”
    name=”__REQUESTDIGEST”
    id=”__REQUESTDIGEST”
    value=”0x5DC31993EF285644A7C48F………..BFA2E6FB719CD7E9DB0922A329E97,19 May 2008 23:37:22 -0000″ />
As you see this is nothing more than a hidden field set by the server and verified back by the server when the page is submitted. As documented by Microsoft: The purpose of form digest validation is to help prevent security attacks where a user is tricked into posting data unknowingly to a server.
The place where the Form Digest value is set is the WebPartPage.FormOnLoad() method:
private void FormOnLoad(object sender, EventArgs e)
{
    if (HttpContext.Current != null)
    {
        SPWebcontextWeb = SPControl.GetContextWeb(HttpContext.Current);
        if(contextWeb != null)
        {
            SPWebPartManager.RegisterOWSScript(this, contextWeb);
            if (this.Page.Items["FormDigestRegistered"] == null)
            {
                stringbstrUrl = SPGlobal.GetVTIRequestUrl(this.Context.Request, null).ToString();
                SPStringCallback pFormCallback = new SPStringCallback();
                contextWeb.Request.RenderFormDigest(bstrUrl, pFormCallback);
                base.ClientScript.RegisterHiddenField(“__REQUESTDIGEST”, SPHttpUtility.NoEncode(pFormCallback.StringResult));
                FormDigest.RegisterDigestUpdateClientScriptBlockIfNeeded(this);
                this.Page.Items["FormDigestRegistered"] = true;
            }
        }
    }
}

The actual value of the __REQUESTDIGEST  field is generated by the COM objects in the OWSSVR.dll. After that another method is called: FormDigest.RegisterDigestUpdateClientScriptBlockIfNeeded()

public static void RegisterDigestUpdateClientScriptBlockIfNeeded(Page page)
{
    doubletotalMilliseconds;

    if (SPContext.Current.Site.WebApplication.FormDigestSettings.Enabled)
    {
        totalMilliseconds = SPContext.Current.Site.WebApplication.FormDigestSettings.Timeout.TotalMilliseconds;
        if(totalMilliseconds > 2147483647.0)
        {
            totalMilliseconds = 2147483647.0;
        }
    }
    else
    {
        return;
    }

    int num2 = Convert.ToInt32((double)(totalMilliseconds * 0.8));
    if(!page.ClientScript.IsOnSubmitStatementRegistered(typeof(FormDigest), “SPFormDigestUpdaterSubmitHandler”))
    {
      page.ClientScript.RegisterOnSubmitStatement(
            typeof(FormDigest),
            “SPFormDigestUpdaterSubmitHandler”,
            “UpdateFormDigest(‘” + SPEncode.ScriptEncode(SPContext.Current.Web.ServerRelativeUrl) + “‘, “+ num2.ToString(CultureInfo.InvariantCulture) + “);”);

        ScriptLink.Register(page, “init.js”, true, false);
    }
} 
There are a couple of interesting pieces of information in the code above. Firstly the Form Digest value generated by the server can expire. By default this happens in 30 min. Secondly the SPWebApplication.FormDigestSettings property can be used to change the form digest settings per web application. Those settings are persisted in the configuration database if you call SPWebApplication.Update(). The information provided in MSDN for the “Enabled” property is however not completely correct. MSDN says that: Enabled gets or sets a value that determines whether security validation is included with all form pages. But my SharePoint code examination and code tests showed that the Form Digest will be always included regardless of the Enabled value. The value of “false” means that when the digest expires (by default in 30 min) the user will not be able to submit the form and will get a security validation timeout exception trying to do so. Further test however showed that setting Enabled to false will indeed disable the security validation and you will not be getting the “The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.” exception even that AllowUnsafeUpdates will have a value of false.
Looking into the code of FormDigest.RegisterDigestUpdateClientScriptBlockIfNeeded() we see that it registers a client script that calls the UpdateFormDigest()  JavaScript function when the form is submitted. This JavaScript function calls the GetUpdatedFormDigest() method of the _vti_bin/sites.asmx WebService and updates the form digest field value on the fly before the form is submitted back to the server. According to the preliminary documentation of the Sites Web Service Protocol released by Microsoft on 4 Apr 2008: The GetUpdatedFormDigest is used to request renewal of an expired security validation, also known as a message digest. The purpose of form digest validation is to help prevent security attacks where a user is tricked into posting data unknowingly to a server.  To generate the new digest the web service simply creates a new instance of the FormDigest control and returns its DigestValue property value. So if the function is not called and the Form Digest is not updated a security timeout exception will occur and users will have to refresh a page before they can submitt it.
So the next question is where is the Form Digest validated? This is actually done in the SPWeb.ValidateFormDigest() method:
public bool ValidateFormDigest()
{
    HttpContext current = HttpContext.Current;

    if (current != null)
    {
        if (HttpContext.Current.Items["FormDigestValidated"] == null)
        {
            if (!this.Request.ValidateFormDigest(this.Url, null))
            {
                return false;
            }

            current.Items["FormDigestValidated"] = true;

            return true;
        }

        return true;
    }

    return true;
}
And as the code above shows the validation is done only once per web request and is then cached in the HTTPContext. Furthermore when a new SPWeb or SPSite object is created they also create an internal SPRequest object from the HTTPRequest. And within the lifetime of a single HTTP request to your web part or a web page, if the Form Digest has been successfully validated once then the AllowUnsafeUpdates property will now have a default value of true for all freshly created objects and the updates will be considered safe by SharePoint which also means you don’t have to set AllowUnsafeUpdates to do your job.
For some reason sometimes SharePoint doesn’t always call the ValidateFormDigest() method and this is why a workaround with setting AllowUnsafeUpdates to true is used. But a much better and safer solution is if you call this method yourself. The best way to do it is to call the SPUtility.ValidateFormDigest() method somewhere at the beginning of your POST request code behind.
And finally if you use in SharePoint you custom built ASPX pages which don’t inherit from a WebPartPage you can insert a FormDigest control in them which will insert the Form Digest  for you automatically and will protect you from cross-site scripting. Just make sure to call ValidateFormDigest() and DON’T touch the AllowUnsafeUpdates.
I hope that my investigation was more useful than confusing to you. Knowing more about how things work is always a key to building better and more secure applications.
Happy coding.