Thursday, August 23, 2012

SharePoint 2010: Howto start customize list form (New/Edit/View) using InfoPath Designer 2010

In SharePoint 2010 there we have more option to customize list form. For instance, you can use SharePoint Designer 2010 or InfoPath Designer 2010. Since modifying list form using SPD is already exist in previous version. I will just show you how to customize list form using InfoPath Designer 2010.
When customizing list form using InfoPath Designer 2010, you will get all form designer benefit. For example, you can define the field validation rules, parent-child relation etc. And bet what, the process is straight forward. In this very basic how-to, I will demonstrate how to start customize list form using InfoPath Designer 2010. I will create an Book List with “Title” – “Author” – “Status” column. In the New form, I will only show “Title” and “Author” – while in Edit form, “Title” and “Author” will be readonly, but “Status” is editable.
How to customize list form using InfoPath Designer 2010.
  1. Prepare the custom list.

    Prepare custom “Book List” with 3 columns: “Title” – “Author” – “Status”. “Status” field is choice “Available” – “In Used” – “Missing”. After creating the list and preparing columns, we can start to use the list and add a new item in this form.
  2. Start InfoPath Designer
    Start InfoPath Designer and select to design SharePoint List form.

    Type in the SharePoint site URL

    And then select the Book List from the list of available data.

    Finally, click on Finish.
  3. When the form editor open , you can start to edit the New form. I add a title “Book List Entry” and delete the “Status” row.

    And here is the result:
  4. Add “Edit Form” view in the designer, and set Title and Author as readonly.

    Type-in the view title.

    Design the form – add “Status” column in the form.

    Set “Title” and “Author” textbox property to “ReadOnly”

  5. Publish the form to the list.
  6. Configure the “Book List” to use designated form.
    Open the list setting page, and expand context menu for the Forms.

    Since the first view will be the default – our interest is only to the “(Item) Edit Form”. Click on (Item) Edit Form link, and change the Form view.
    You will realize that now you are seeing form services in web part.

    Click on Web Parts Tools tab, and then click on Web Part Properties.

    In the Web Part Properties, select the designated view.
  7. And here we go with the custom “New Form” and “Edit Form” for the list.
    New Form.

    Edit Form.

Wednesday, August 22, 2012

SharePoint 2010 - SharePoint Object Model


For programming against the SharePoint items, we need to retrieve the properties and the methods to operate on them. The SharePoint Object Model provides various classes to accomplish this. In this article we can discuss the Object Model with the core classes involved with little amount of coding.

Please note that there are 2 Object Models in SharePoint 2010:

  1. Server Object Model
  2. Client Object Model
Here we are discussing only about the Server Object Model. Server Object Model classes are used for server-side programming and will be executed on the SharePoint Server Farm.

Namespace

The Server Object Model classes are residing in the Microsoft.SharePoint assembly. The general classes are available in the Microsoft.SharePoint namespace and the administration classes inside the Microsoft.SharePoint.Administration namespace.

Core Classes

Following are the important classes and their corresponding SharePoint items.

Class
SharePoint Item
SPFarm
Farm
SPServer
Server
SPSite
Site Collection
SPWeb
Web site
SPControl
Control
SPList
List
SPDocumentLibrary
Document Library
SPContentType
Content Type
SPUser
User
SPException
SharePoint Exception

Programming

Now we can start experimenting with some of the above classes. To begin we can create a SharePoint Console Application. Use the New Project > SharePoint > Console Application project item.

ShareObjM1.jpg

Accessing the List Items in a List

For proceeding with this example, create a list derived from the Contacts template and name it as "My Contacts".

Add some items inside it with the First Name and Last Name set.

Use the following code inside the Console application and execute it.
using (SPSite site = new SPSite("http://appes-pc/my/personal/dotnet")) // Site Collection{
    using (SPWeb web = site.OpenWeb()) // Site    {
        SPList list = web.Lists["My Contacts"]; // List        int i = 1;
        foreach (SPListItem item in list.Items)
        {
            Console.WriteLine("Item: " + (i++).ToString());

            Console.WriteLine(item.Name);
            Console.WriteLine(item.Title);
            Console.WriteLine(item.GetFormattedValue("First Name"));
            Console.WriteLine(item.GetFormattedValue("Last Name"));
            Console.WriteLine(string.Empty);
        }
    }
}
Console.ReadKey(false);

If you receive any build errors regarding a namespace, change the Project Properties > Target to .Net Framework 3.5.
ShareObjM2.jpg

Now try building the application and it should work fine. You will see the following output.
ShareObjM3.jpg

Please note the use of Title and Name properties and the GetFormattedValue() method.

Accessing the items in a Library

Now we can proceed with accessing the document library items programmatically. For proceeding you need to create a document library inheriting from the Document Library template and name it "My Docs". Upload one or two documents into it. We are proceeding to get the file name and length in this example.

Enter the following code in the console application.
using (SPSite site = new SPSite("http://appes-pc/my/personal/dotnet")) // Site Collection{
    using (SPWeb web = site.OpenWeb())                    // Site    {
        SPDocumentLibrary library = web.Lists["My Docs"] as SPDocumentLibrary; // Library        int i = 1;
        foreach (SPListItem item in library.Items)
        {
            Console.WriteLine("Item: " + (i++).ToString());
            Console.WriteLine(item.File.Name);
            Console.WriteLine(item.File.Length);
            Console.WriteLine(string.Empty);
        }
    }
}


Executing the application, you will see the following results.

ShareObjM4.jpg

SPControl

The SPControl class acts as the base class while developing server controls. It reseides in the namespace Microsoft.SharePoint.WebControls.

SPControl provides static methods that returns reference to the current site, web, web application, module. The methods are:
SPControl.GetContextSite()SPControl.GetContextWeb()SPControl.GetContextWebApplication()SPControl.GetContextModule()

SPException

The SPException class can be used to handle an exception in a try catch block. It represents the exceptions thrown by the server object model.
try{
    // Code here}
catch (SPException ex)
{
    // Handle Exception}


SPUser

The SPUser class can be used to access user information for a SharePoint site. Enter the following code to get the number of users and their names.
using (SPSite site = new SPSite("http://appes-pc/my/personal/dotnet"))
{
    using (SPWeb web = site.OpenWeb())
    {
        foreach (SPUser user in web.AllUsers)
            Console.WriteLine("User: " + user.Name);
    }
}


On running the code you will see the results based on your machine users.

ShareObjM5.jpg

Note

You can add a new list item or library item using the Items.Add() method. For updating and deleting use the item.Update() and item.Delete() methods respectively. More code coverage on these areas will be provided later.

References

http://msdn.microsoft.com/en-us/library/ms473633.aspx
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.spcontrol.aspx
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spuser.aspx

Summary

In this article we have explored the SharePoint Object Model and some basic coding examples with List and Library. The advanced coding examples will be provided at a later point of time.

SharePoint 2010 Client Object Model: Introduction

Introduction

In this article I would like to discuss about the Client Object Model feature of SharePoint 2010.

Overview

Client Object Model is a new feature of SharePoint 2010. It provides features to program against a SharePoint site using .NET Managed Code or JavaScript.
The Client Object Model provides almost all the programming features of the Server Object Model plus advantages in deployment. The Client OM (Client Object Model) is being used as the core programming aid for SharePoint 2010 and thus widely used in the market.

Advantages

  1. Less Deployment Hassles: Using Client OM, you do not need to install the components required by the Server Object Model. Thus Client OM provides much ease to the end user.
  2. Language Flexibility: We can use the following languages to work with the Client OM:
    1. Microsoft .NET
    2. Silverlight
    3. ECMA Script (JavaScript /JScript)
  3. Query Speed Optimizations: In the Client OM, reduced network traffic is attained using Query Optimizations. Thus the user will feel reduced round trips and other advantages like paged results, etc.

How it works?

The Client OM works by sending an XML Request. The server will return a JSON response which is converted to the appropriate Object Model.

Supported Languages

Following are the programming language/platforms supported for Client Object Model:
  • .NET Languages (C#, VB.NET etc.)
  • Silverlight
  • Scripting Languages (JavaScript, Jscript)

Core Assemblies

There are two assemblies to be referred for working with the Client Object Model.
  1. Microsoft.SharePoint.Client.dll
  2. Microsoft.SharePoint.Client.Runtime.dll
These assemblies can be found in the 14 Hive folder: %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI.

Classes inside Client Object Model

In C#, comparing with classes of the Server Object Model, we can see that Client Object Model has similar classes with a suffix in the namespace and no SP prefix in the class name.
For example: SPSite in the Server Object Model is represented in the Client OM as Site with namespace Microsoft.SharePoint.Client.
Client Object ModelServer Object Model
Microsoft.SharePoint.Client.ClientContextSPContext
Microsoft.SharePoint.Client.SiteSPSite
Microsoft.SharePoint.Client.WebSPWeb
Microsoft.SharePoint.Client.ListSPList

Example

Following is an example of retrieving a list from the server using Client OM:
ClientContext context = new ClientContext("http://hp");
List list = context.Web.Lists.GetByTitle("Tasks");
context.Load(list);
context.ExecuteQuery();

Console.WriteLine(list.Title);
Console.ReadKey(false);
I should remark something about the above code:
  • Even though there are multiple calls, they are not sent to the server until ExecuteQuery() is called.
  • Network round trips between the client and server are reduced by combining multiple calls into one.
  • Object Identity is used to setup the queries. Object Identities are those which refer to the Server Object ModelObject Identities are valid only for the current client context.

More Examples with Client Object Model

Here I would like to list some examples using the Client Object Model. For starting with the examples, please do the following:
  1. Create a Windows Application
  2. Change the Target Framework to .NET 4.0
  3. Add reference to Microsoft.SharePoint.Client, Microsoft.SharePoint.Client.Runtime
Before continuing with the examples, please ensure the site has valid data items in the Tasks list. We will be changing the data items during our session.

1. Get List Items

Here we are querying the list items of the Tasks list.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");
CamlQuery query = new CamlQuery();
query.ViewXml = "<View/>";
ListItemCollection items = list.GetItems(query);

context.Load(list);
context.Load(items);

context.ExecuteQuery();
After executing the code, the result can be stored into a DataTable as shown below.
DataTable table = new DataTable();
table.Columns.Add("Id");
table.Columns.Add("Title");

foreach (ListItem item in items)
    table.Rows.Add(item.Id, item["Title"]);

datagrid.DataSource = table;
On my machine, the data retrieved is shown below:

2. Update List Items

Here I would like to show the modification code. All the titles are appended with two asterisks whose IDs are even number.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");
CamlQuery query = new CamlQuery();
query.ViewXml = "<View/>";
ListItemCollection items = list.GetItems(query);

context.Load(items);

context.ExecuteQuery();

foreach(ListItem item in items)
    if ((item.Id % 2) == 0)
    {
        item["Title"] += "**";
        item.Update();
    }

context.ExecuteQuery();
After executing the query, please refresh the data grid using the Get Data button. You can see the following result.

You can see that the Titles are modified for those with even number IDs.

3. Get By Row Limit

Here we can experiment with the RowLimit tag inside CAML queries. You can note that while accessing the list we are actually using a CAMLQuery class instance. Inside the query it is possible to set the RowLimit tag as well.
The RowLimit tag restricts the number of items retrieved from the server. Thus we can save a lot of bandwidth by reducing the rows while doing search.
ClientContext context = new ClientContext(ServerText.Text);
Web web = context.Web;

List list = web.Lists.GetByTitle("Tasks");

CamlQuery query = new CamlQuery();
query.ViewXml = "<View><RowLimit>3</RowLimit></View>";

ListItemCollection listItems = list.GetItems(query);

context.Load(listItems);
context.ExecuteQuery();
You can see that the RowLimit is set to 3. On executing the query and displaying the results to a data grid, you can see three items as shown below.

4. Get By Search Criteria

Now we can try selecting the list items using the search criteria. Here we are trying to get the items of Status as ‘In Progress’.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");

CamlQuery query = new CamlQuery();
query.ViewXml = @"<View>
    <Query>
        <Where>
        <Eq>
            <FieldRef Name='Status'/>
            <Value Type='Text'>In Progress</Value>
        </Eq>
        </Where>
    </Query>
    </View>";

ListItemCollection listItems = list.GetItems(query);
context.Load(listItems, items => items.Include(
                                                item => item["Id"],
                                                item => item["Title"],
                                                item => item["Status"]
                                                ));
context.ExecuteQuery();
On executing the code above, you will get the results filtered by the Status field.

5. Insert an Item

Here we can try inserting a new item into the Tasks list.
ClientContext context = new ClientContext(ServerText.Text);
Web web = context.Web;

List list = web.Lists.GetByTitle("Tasks");

ListItemCreationInformation newItem = new ListItemCreationInformation();
ListItem listItem = list.AddItem(newItem);
listItem["Title"] = "New Item Created through C#";
listItem.Update();

context.ExecuteQuery();
You can see that we are using a new class named ListItemCreationInformation along with the ListItem class. This information will be recorded and passed to the server once the ExecuteQuery() method is called.
On executing the above code and retrieving the results, you can see the output as below:

6. Update an Item

The Update operation is next in the series of the CRUD pattern. Already we have seen updating the Title. Here you can see how to update the Status.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");
CamlQuery query = new CamlQuery();
query.ViewXml = "<View/>";

ListItemCollection listItems = list.GetItems(query);

context.Load(listItems);

context.ExecuteQuery();

ListItem item = listItems[listItems.Count - 1];
item["Status"] = "In Progress";
item.Update();

context.ExecuteQuery();
On executing the code, you can see that the last item was updated.

7. Delete an Item

Now we can try deleting an item from the List. Here is the code to achieve that.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");

ListItemCollection listItems = list.GetItems(new CamlQuery() { ViewXml = "<View/>" });
context.Load(listItems);
context.ExecuteQuery();

listItems[listItems.Count - 1].DeleteObject();
context.ExecuteQuery();
We need to call the DeleteObject() method of the item followed by the ExecuteQuery().

8. Reducing the Result Size by Specifying Properties

So what if you wanted only one property value for an item with 10 properties? There will be unwanted transferring of 9 columns. Here we can see how to specify only the needed columns for an item.
ClientContext context = new ClientContext(ServerText.Text);
Web web = context.Web;

context.Load(web, w => w.Title);
context.ExecuteQuery();

MessageBox.Show("The title is: " + web.Title);
MessageBox.Show("Now trying to access a field not in Result Set (expect exception)");

try
{
    MessageBox.Show(web.Description); // You will get Error here
}
catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}
Here we can see that only the Title property has been specified for retrieval. Accessing the Description column throws an exception.

9. Reducing the Result Size in List

In the case of the list the problem is worse as there are n number of columns for the list. The result will be multiplied n times. So if we need only 1 column and retrieve 10 columns for a list of 1000 items, we end up getting 9 x 1000 unwanted column values.
So to specify the list columns in the Result Set the syntax will be slightly different.
ClientContext context = new ClientContext(ServerText.Text);
List list = context.Web.Lists.GetByTitle("Tasks");

CamlQuery query = new CamlQuery();
query.ViewXml = "<View/>";
ListItemCollection listItems = list.GetItems(query);

context.Load(listItems, items => items.Include(item => item["Id"]));

context.ExecuteQuery();
Please note the way Id is specified. While filling the results, you should take care that only the ID column value is accessed.
DataTable table = new DataTable();
table.Columns.Add("Id");

foreach (ListItem item in listItems)
    table.Rows.Add(item.Id);

datagrid.DataSource = table;

10. Specifying Credentials

You can specify user credentials while accessing the SharePoint server. The property Credentials is for this purpose.
ClientContext context = new ClientContext(ServerText.Text);
context.Credentials = new NetworkCredential("User", "Password");

Web web = context.Web;
context.Load(web);

context.ExecuteQuery();
MessageBox.Show(web.Title);
Please specify the correct user name and password of your site otherwise an Unauthorized Exception will be thrown.
So this concludes the article with Client Object Model examples for the most common scenarios. In the real world you will need much more complicated steps and I believe these will provide a base to achieve them.

When to use Server Object Model?

We can use it on the SharePoint server where the Server Object Model binaries are available. Typical example would be inside Web Parts / Workflows.

When to use Client Object Model?

We can use it from client machines where the entire SharePoint binaries are not available. A typical example would be from a Windows Forms application in a client machine.

Summary

In this article we have seen an overview of the Client Object Model in SharePoint 2010. The source code attached contains various samples of working with the Client Object Model.

Developing SharePoint 2010 features using Visual Studio 2010

Developers can extend SharePoint by creating new features. Using features developers can develop customizations and extensions that can be capable of automated deployment, management, un-installation and upgrading. SharePoint Feature allows developer to create a set of functionality to group into a component and allows administrators to add that functionality to the site/site collection. In addition to this, administrator can disable or uninstall the feature if they wish. With SharePoint 2010, it is possible to upgrade the feature to a new version. In this article I am going to demonstrate how to create a feature using SharePoint 2010.
In SharePoint, each feature has its own folder. If your SharePoint is installed in default location, you can find all the features installed in the farm from the following location
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES
All the features installed in SharePoint farm will have a corresponding folder here. Open any one folder you may see the files inside each folder. Let us examine the feature folder. For this purpose, I have opened the feature folder for HelpLibrary, that is available with default SharePoint installation.
clip_image001
Every feature will have at least one file named Feature.XML called as feature manifest. A feature folder contains all the files required to implement the feature along with the feature manifest file. Other than feature manifest file, there can be other XML files and folders exists in the feature folder. Basically a feature is a set of XML documents, 1 feature manifest file and other elements manifest files. Features may also contain other types of files such as css files, aspx files, images etc.
Basically you can create a feature by using any text editor, but in this article I am going to demonstrate how to develop a feature using Visual Studio.
For this demonstration, I am going to create a aspx page that just says “Welcome to My site” and add a menu item to the SharePoint that link to the page. In real time you may add web parts, list definitions, content types, list instances, image files etc to the feature. So let me start creating the feature.
First you open Visual studio then select file -> New project, the new project dialog will appear. From the templates section, select Visual C# -> SharePoint -> 2010. Make sure the framework selected is .net framework 3.5. I named my project as “SayHelloFeature”, you are free to choose any name, and then choose a location for the project. Click ok once you are done.
clip_image003
SharePoint customization wizard will appear now. Enter the url for the SharePoint portal where you want to do the debugging. When developing a feature using Visual Studio gives you an edge here. Visual Studio will do the packaging and deploying part as you might need to do this several times during development. In my case I need to deploy the feature to the entire farm, so I select the option deploy as farm solution. Click on the finish button once you are done.
clip_image004
Now visual studio will create a minimal SharePoint project for you. See the snapshot of the project in the solution explorer.
clip_image005
Right click on the Features and select Add Feature. The solution explorer will look as follows
clip_image006
Also Visual Studio will provide a dialog for updating the feature properties. You can provide a title and description for the feature and select the scope of the feature – means where it needs to be deployed. Since I want to deploy this feature in a site level, I select “Web” as the scope of my feature.
clip_image008
You can see the source of the application by clicking on the manifest link and you have the option to view and edit the feature.xml file directly.
clip_image009
You can set the version of the feature using the property dialog; the feature will be used by SharePoint 2010 when you upgrade the solution.
From solution explorer, right click the project, select Add -> new Item, the new item dialog appears. Select module as the item template, enter a name, I just kept the name as Module1 (default one suggested by Visual Studio). Click Add once you are done.
clip_image011
From the solution explorer, the view of the project looks as below.
clip_image012
When adding a new module, visual studio will automatically add an element manifest file and a Sample.txt file to the Module. Element manifest file is an xml file (Elements.xml – it can be any name as there is no restriction on the name, but if you change the name, make sure you update the feature definition with the corresponding name) that keeps track of all module files. In my feature, I don’t need sample.txt file, delete sample.txt by right click on it and select delete.
Now you need to add an aspx page to the Module that says Hello to the user. To add a simple aspx file, there is no straight forward method available in VS2010, you can follow the below steps.
(Visual Studio doesn’t provide a direct way to add an aspx page, so just choose text file as file type and then name it with .aspx extension)
Right click module1 and the select Add -> New Item, then select General from the template, choose text-file as the template and name the file as Hello.aspx
clip_image014
Now you need to add the markup for the aspx page. You need to do this manually. Don’t forget to refer the default SharePoint assemblies. I have added the below markup to the hello.aspx page, You just need to make sure that the required content place holders are there in the new page, all the other content you are free to make it your own.

<%@ Page MasterPageFile="~masterurl/default.master" meta:progid="SharePoint.WebPartPage.Document" %>
<asp:Content ID="title" runat="server" ContentPlaceHolderID="PlaceHolderPageTitle">
   Saying Hello
</asp:Content>
<asp:Content ID="addhead" runat="server" ContentPlaceHolderID="PlaceHolderAdditionalPageHead">
</asp:Content>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="PlaceHolderMain">
   <h3>Hello, Welcome to My Site</h3>
</asp:Content>
Now we are done with the aspx page. For the demonstration purpose, I am going to add a menu item that links to the newly created page. For such purposes, SharePoint provides custom action using which you can add menu items to SharePoint.
From the solution explorer, right click the project, select Add -> New Item. In the template list, you will not find a template with the name custom action, so select empty element; - You can use empty element when none of the templates matches a particular type of item.
For understanding more about custom actions read the below 2 posts
http://msdn.microsoft.com/en-us/library/ms460194.aspx
http://msdn.microsoft.com/en-us/library/bb802730.aspx
In the elements.xml under new empty element just added, paste the below xml
<CustomAction Id="SiteActionsToolbar" GroupId="SiteActions"
Location="Microsoft.SharePoint.StandardMenu" Sequence="100" Title="Say Hello"
Description="A page saying hello"><UrlAction Url="~site/SitePages/Hello.aspx"/>
</CustomAction>
Save the file, now you are done with the custom action. Let us examine the feature file. Go to the feature page and make sure feature contains all the items you have added.
clip_image016
Now the solution is ready to deploy. From solution explorer, right click the project and click deploy.
clip_image017
Now visual studio will deploy the feature to the farm and activate it. Once deployed, go to the features folder under 14 hive and you will see your feature folder there. See the snapshot of the SayHello feature folder, once deployed.
clip_image018
Once the feature is activated, You can see the menu item is added to the Site Actions menu of your site.
clip_image019
Click on the Say Hello link, you will be redirected to the page.
clip_image020
Visual Studio makes it easy for developers to build features for SharePoint 2010. Developers have complete control over each components of the feature. The one click deployment saves lot of developer time as they should not worry about the administrative process involved in the installation process. In addition to all these, Visual Studio will package your solution as WSP file, in single click so that you can package your solution and deploy it to production servers.

http://blogs.msdn.com/b/sharepointdev/

http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepoinhttp://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/http://blogs.msdn.com/b/sharepointdev/tdev/http://blogs.msdn.com/b/sharepointdev/