Wednesday, December 29, 2010

My First Silverlight and SharePoint 2010 application using client side object model

This is my first post on Silverlight + SharePoint 2010 and it will take you through a very simple example of using a Silverlight application in SharePoint 2010, using the new SharePoint 2010 Client Object Model.
I will also show how to do deployment of Silverlight application in SharePoint 2010.
Visual Studio 2010 provides good development tools for SharePoint 2010 as well as for Silverlight.
Note that I will not be getting into the details of creating a flashy User interface (UI) in Silverlight – i will just create a very simple UI with a Data Grid view, text boxes and buttons.

The Example is divided into 3 sections.  As follows…..
  1. Create UI in Silverlight.
  2. Use Client side object model to Add, Update, Delete and retrieve records of SharePoint 2010 list from Silverlight 4 Application.
  3. Create a SharePoint 2010 solution which will deploy a Silverlight XAP file to SharePoint.

Section 1: Create UI in Silverlight

I am going to create a simple Silverlight form for Contact Management. And it contains two textboxes, two buttons (Add and Update) and one Data Grid View with three columns (Name, Address and Actions). 

1. First of all create one Silverlight Application for that go to New Project > Select Silverlight > Select Silverlight Application > Enter Name of Application.
2. Uncheck the “Host the Silverlight application in a new web site” option. We don’t need it. And select Silverlight version probably 4.
     3.Open MainPage.xaml file in Design mode. And add two textboxes, two buttons (Add and Update) and one Data Grid View. Page will look like this…
4. Open MainPage.xaml file in XAML mode. And addfollowing XMAL code in Data Grid tag for columns creation. There are three columns first is Name, second is Address and third is Actions. Actions column contains two image buttons Edit and Delete.
XAML Code
<data:DataGridAutoGenerateColumns="False" Height="140"HorizontalAlignment="Left" Margin="7,153,0,0" Name="DataGridContacts"IsReadOnly="True"VerticalAlignment="Top" Width="379" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="150" />
<data:DataGridTextColumn Binding="{Binding Address}" Header="Address" Width="150" />
<data:DataGridTemplateColumn Header="Actions">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanelVerticalAlignment="Center">
<GridVerticalAlignment="Center" Width="70">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="btnEdit"Grid.Column="0"CommandParameter="{Binding ID}" Content="{Binding ID}" Width="23" Height="23" Click="btnEdit_Click">
<Button.Template>
<ControlTemplate>
<Image Source="/SilverlightDataEntryApplication;component/Images/Edit.png" Height="23" Width="23" />
</ControlTemplate>
</Button.Template>
<ToolTipService.ToolTip>
<ToolTip Content="Edit Contact"></ToolTip>
</ToolTipService.ToolTip>
</Button>
<Button x:Name="btnDelete"Grid.Column="1" Margin="5" Click="btnDelete_Click"CommandParameter="{Binding ID}">
<Button.Template>
<ControlTemplate>
<Image Source="/SilverlightDataEntryApplication;component/Images/Delete.png" Height="25" Width="25" />
</ControlTemplate>
</Button.Template>
<ToolTipService.ToolTip>
<ToolTip Content="Delete Contact"></ToolTip>
</ToolTipService.ToolTip>
</Button>
</Grid>
</StackPanel>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>

Section 2: Use Client side object model to Add, Update,Delete and retrieve records of SharePoint 2010 list from Silverlight 4 Application.

1.    Add Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll references in the project.
2.       Add code in MainPage.xaml.cs file. The following example shows how to create, Update and delete a list item in a specific SharePoint 2010 list.
Here I have demonstrated two differentmethods to access data from SharePoint 2010 List.
The example uses a delegate to Add, update and Delete the information of the item in the UI. And the example uses BackgroundWorkerthread for retrieving items from SharePoint 2010 list.
NoteImportant!
While accessing data from multiple lists, you cannot use delegate to access data, for the same you can useBackgroundWorker.
We cannot run the data retrieval methods on UI thread of the Silverlight Application. For that we have to create a new thread using BackgroundWorkerand call data retrieval methods from the new thread’s DoWork method.
C# Code
using System;
usingSystem.Collections.ObjectModel;
usingSystem.ComponentModel;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingMicrosoft.SharePoint.Client;
namespaceSilverlightDataEntryApplication
{
publicpartialclassMainPage : UserControl
    {
        #region Global Variables
BackgroundWorkerbwLoadContacts = newBackgroundWorker();
ObservableCollection<ContactInfo>gContactCollection = null;
intgSelectedID = 0;
stringgSelectedName = string.Empty;
stringgSelectedAddress = string.Empty;
ListItemgListItem = null;
        #endregion
publicMainPage()
        {
InitializeComponent();
bwLoadContacts.DoWork += newDoWorkEventHandler(bwLoadContacts_DoWork);
bwLoadContacts.RunWorkerCompleted += newRunWorkerCompletedEventHandler(bwLoadContacts_RunWorkerCompleted);
LoadContacts();
        }
        #region Load Contacts from SharePoint List and Bind to DataGrid
privatevoidLoadContacts()
        {
//Run BackgroundWorker Thread Here!
if (!bwLoadContacts.IsBusy)
            {
bwLoadContacts.RunWorkerAsync();
            }
        }
voidbwLoadContacts_DoWork(object sender, DoWorkEventArgs e)
        {
//Write Data Retrival Code Here!
ClientContextoClientContext = newClientContext(ApplicationContext.Current.Url);
ListoList = oClientContext.Web.Lists.GetByTitle("Contacts");
oClientContext.Load(oList);
CamlQueryoCamlQuery = newMicrosoft.SharePoint.Client.CamlQuery();
            #region CAML
stringstrCAMLQueryXML = string.Format(@"<View>
<Query>
<OrderBy>
<FieldRef Name='Name' />
</OrderBy>
</Query>
</View>");
            #endregion
oCamlQuery.ViewXml = strCAMLQueryXML;
ListItemCollectionoListItemCollection = oList.GetItems(oCamlQuery);oClientContext.Load(oListItemCollection);
oClientContext.ExecuteQuery();//Execute Query Synchronously
gContactCollection = newObservableCollection<ContactInfo>();
foreach (ListItemoIteminoListItemCollection)
            {
ContactInfo contact = newContactInfo();
                contact.ID = oItem.Id;
contact.Name = Convert.ToString(oItem["Name"]);
contact.Address = Convert.ToString(oItem["Address"]);
gContactCollection.Add(contact);//Add to global Variable
            }
        }
voidbwLoadContacts_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
//Write Data Binding Code Here!
DataGridContacts.ItemsSource = gContactCollection;
TxtName.Text = "";
TxtAddress.Text = "";
        }
        #endregion
privatevoidBtnAdd_Click(object sender, RoutedEventArgs e)
        {
LblMessage.Content = "Adding Record...";
gSelectedName = TxtName.Text;
gSelectedAddress = TxtAddress.Text;
ClientContextoClientContext = newClientContext(ApplicationContext.Current.Url);
ListoList = oClientContext.Web.Lists.GetByTitle("Contacts");
oClientContext.Load(oList);
gListItem = oList.AddItem(newListItemCreationInformation());
gListItem["Name"] = TxtName.Text;
gListItem["Address"] = TxtAddress.Text;
gListItem.Update();
oClientContext.Load(gListItem);
oClientContext.ExecuteQueryAsync(OnRequestSucceeded, null);
        }
privatevoidBtnUpdate_Click(object sender, RoutedEventArgs e)
        {
LblMessage.Content = "Updating Record...";
ClientContextoClientContext = newClientContext(ApplicationContext.Current.Url);
ListoList = oClientContext.Web.Lists.GetByTitle("Contacts");
oClientContext.Load(oList);
gListItem = oList.GetItemById(gSelectedID);
gListItem["Name"] = TxtName.Text;
gListItem["Address"] = TxtAddress.Text;
gListItem.Update();
oClientContext.Load(gListItem);
oClientContext.ExecuteQueryAsync(OnRequestSucceeded, null);
        }
privatevoidbtnDelete_Click(object sender, RoutedEventArgs e)
        {
if (MessageBox.Show("Are you sure you want to remove this contact?","Delete Contact",MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
//Delete Record
LblMessage.Content = "Deleting Record...";
Button _btn = (Button)sender;
int ID = Convert.ToInt32(_btn.CommandParameter.ToString());
ClientContextoClientContext = newClientContext(ApplicationContext.Current.Url);
ListoList = oClientContext.Web.Lists.GetByTitle("Contacts");
oClientContext.Load(oList);
gListItem = oList.GetItemById(ID);
gListItem.DeleteObject();
oClientContext.Load(oList);
oClientContext.ExecuteQueryAsync(OnRequestSucceeded, null);
            }
        }
privatevoidOnRequestSucceeded(Object sender, ClientRequestSucceededEventArgsargs)
        {
// this is not called on the UI thread          
Dispatcher.BeginInvoke(ShowMessage);
        }
privatevoidShowMessage()
        {
LblMessage.Content = "Operation Completed Successfully!";
LoadContacts();
        }
privatevoidbtnEdit_Click(object sender, RoutedEventArgs e)
        {           
Button _btnEdit = (Button)sender;
gSelectedID = Convert.ToInt32(_btnEdit.CommandParameter.ToString());
GetContactByID(gSelectedID);
        }
privatevoidGetContactByID(int ID)
        {
ClientContextoClientContext = newClientContext(ApplicationContext.Current.Url);
ListoList = oClientContext.Web.Lists.GetByTitle("Contacts");
oClientContext.Load(oList);
gListItem = oList.GetItemById(ID);
oClientContext.Load(gListItem);
//gContentsCollection.RetrieveItems().Retrieve();
oClientContext.ExecuteQueryAsync(OnRequestSucceeded_Load, null);
        }
privatevoidOnRequestSucceeded_Load(Object sender, ClientRequestSucceededEventArgsargs)
        {
// this is not called on the UI thread          
Dispatcher.BeginInvoke(BindData);
        }
privatevoidBindData()
        {
gSelectedID = gListItem.Id;
TxtName.Text = Convert.ToString(gListItem["Name"]);
TxtAddress.Text = Convert.ToString(gListItem["Address"]);
        }       
    }
publicclassContactInfo
    {
publicint ID { get; set; }
publicstring Name { get; set; }
publicstring Address { get; set; }
    }
}

Section 3: Create a SharePoint 2010 solution which will deploy a Silverlight XAP file to SharePoint.

1.       Create an Empty SharePoint 2010 project with Deploy on farm solution is checked.
2.       Map ClientBin SharePoint folder from layouts.

3.       Create a new folder as ContactsDemoin ClientBin folder.
4.       Add post-build command as “xcopy  "$(TargetDir)SilverlightDataEntryApplication.xap" "$(SolutionDir)DeploySilverlightToSharePoint\ClientBin\ContactsDemo\" /Y” in the Silverlight project SilverlightDataEntryApplication.
5.       BuildSilvelright Project. One file will be copied to DeploySilverlightToSharePoint\ClientBin\ContactsDemo\ location.
6.       Include SilverlightDataEntryApplication.xapfile in SharePoint Project. Build the SharePoint project and deploy the solution.
7.       Open SharePoint Site and Add Silverlight Web part from the media group on the page.
8.       Go to edit web part and Click on Configure button.
9.       Popup will open with one textbox, enter XAP file path as “_LAYOUTS\ClientBin\ContactsDemo\SilverlightDataEntryApplication.xap” and click in OK Button.

Tuesday, December 21, 2010

LINQ Can Improve Your C# Programming

Introduction

LINQ has its own set of Query operators which make it powerful. These exist in the System.LinqSystem.Core assembly. These are extension methods on the Enumerable and Queryable objects. Namespace within the
The standard LINQ query operators can be classified into the following types:

Qualifiers Operators
Any, All, Contains
Set Operators
Distict, Union, Intersect, Except
Ordering Operators
OrderBy, OrderByDescending , ThenBy , ThenByDescending , Reverse
Equality Operators
SequenceEqual
Conversion Operators
Cast, ToArray, ToList, ToDictionary, OfType, SingeOrDefault
Grouping Operators
GroupBy
Joining operators
Join, GroupJoin
Element Operators
First, FirstOrDefault,ElementAt
Partitioning Operators
Take, Skip, TakeWhile, SkipWhile
Projection Operators
Select , SelectMany
Aggregate Operators
Count, Sum ,Min, Max, Average, Aggregate
Restriction Operators
Where
Concatenation operators
Concat
Generation Operators
Range, Repeat

This article will focus on a handful of LINQ queries that can improve our C# programming.

1.   Avoiding FOREACH on Collections to Filter for Data

You can avoid the FOREACH and the IF clauses inside your FOREACH to filter for data. Check the below sample that eliminates the confusing conditional statements with a simpler LINQ query.
LINQ CODE
 var filteredUsers = from currentUser in Users
                                where currentUser.Active && currentUser.AllowLogin&& ! urrentUser.LoggedIn
                                select user;

2.   Select X Rows

When we have to select a few rows from a collection, we check the loop counter with a fixed constant and break the for loop or control the loop counter.
               
LINQ CODE
 var filteredUsers = Users.Where(u => u.Active && u.AllowLogin && !u.LoggedIn)
                                                  .Take(10)

3.   Take the First Element from a Collection

We face lot of situations where we have to read the first element in a collection. We would start off by evaluating the collection with null and then its elements count and so on. Now, there is a possibility that this collection might be empty.

LINQ CODE
List<string> adminUsers = RetrieveUsersForAdminRole(RoleType.Admin);
  User firstUser = adminUsers.FirstOrDefault();
   If there are no users found, it returns the default value of the underlying type.

4.   Let Go the IComparer<T> for Sorting

We no more need to write the tough IComparer classes to sort our custom data. We can now use the OrderBy method to order the data. Look at the sample query below for more brevity.
LINQ CODE
var filteredUsers = Users.Where(u => u.Active && u.AllowLogin && !u.LoggedIn).OrderBy( u => u.Name);

The ORDERBY function takes in a parameter that is used to sort. If you want do a multi-sort , use the THENBY operator.
LINQ CODE
var filteredUsers = Users.Where(u => u.Active && u.AllowLogin && !u.LoggedIn).OrderBy( u => u.Name).ThenBy(u => u.Location);
  
Yes, you can sort in a Descending fashion too. LINQ provides the ORDERBYDESCENDING operator for this very purpose.

LINQ CODE
var filteredUsers = Users.Where(u => u.Active && u.AllowLogin && !u.LoggedIn).OrderByDescending( u => u.Name).ThenBy(u => u.Location);
                                 
Note: There is a ThenByDescending operator too.

5.   Do Not Use for Loops to Initialize Arrays

Do not use for loops to initialize arrays. We do this a lot of times to write quick test code. This can be replaced using the System.Linq.Enuemerable.Range method.
Using LinQ it is just one line of code.

LINQ CODE
 int[] monthsInAYearByLINQ = System.Linq.Enumerable.Range(1, 12).ToArray();
                 

6.   Replace Two Similar Loops with Concat

If you have to loop through two arrays which are similar in nature, you can use the Concat extension and write concise code. Now, consider this piece of code which uses the Concat operator.

LINQ CODE
int[] firstArray       = System.Linq.Enumerable.Range(1, 12).ToArray();
int[] secondArray = System.Linq.Enumerable.Range(13, 12).ToArray();
  
foreach (var a in firstArray.Concat(secondArray))
{
allElements.AppendLine(string.Format("{0}", a));
}
                 

7.   Avoid Transformations

A transformation is a technique that you follow to return a new collection that is obtained by looping through another collection and applying filters on them.
Instead of creating a temporary list and then filling it up with users, we can use the LINQ SELECT and the ToArray Method to return the results for us.
LINQ CODE
public Users[] FindUsers(RoleType r)
  {
      return FindUsers()
          .Select(user => new User
                          {
                                FirstName = u.FirstName,           
                                     …
                              });
                 .Where(user => user.Role == r)
          .ToArray();
  }

8.   The Let Keyword

The LET keyword lets you build temporary variables in your LINQ query, so that your SELECT query becomes easier to read, and maintain. It lets you predefine variables at a certain stage of the query that can be used in the rest of the query.
For example, the following query calculates the average twice. This can be replaced by using the LET operator. The query will perform faster as the Average is not calculated twice.
LINQ CODE(Simple Query)
var results= from store in Stores where store.Sales.Average(s => s.Price) > 500
select new
{
Name = store.Name
StoreAveragePrice = store. Sales.Average(s => s.Price)
 };

See the following snippet that uses the LET keyword.
LINQ CODE(Query using Let)
var results= from store in Stores
let AveragePrice =  store.Sales.Average(s => s.Price)
 where AveragePrice > 500
select new
 {
Name = store.Name
StoreAveragePrice = AveragePrice
 };
                 

9.   RegEx + LINQ?

LINQ queries can help you work with Regular Expression results and make your henceforth queries simpler. Look at the following sample that iterates over a collection iterating them over the regex expression.
Note that you can do other LINQ queries on the RegEx Matched results.

LINQ CODE
List<string> examinerStatements = new List<string>();
examinerStatements.Add("Mark was present.");
examinerStatements.Add("Julie was present.");
examinerStatements.Add("John was absent");
 
System.Text.RegularExpressions.Regex myRegEx = new System.Text.RegularExpressions.Regex("present");
 
var presentStudents = examinerStatements
.Where<string>(statement => myRegEx.IsMatch(statement))
.ToList<string>();
 
foreach (var examinerStatement in presentStudents)
{
       //
}
                 

10. Querying ArrayList

You would have found that you cannot run LINQ queries on an ArrayList. That is because it does not implement the System.Collections.Generic.IEnumerable<T> interface.

LINQ CODE
List<string ArrayList myList = new ArrayList();
                                myList.Add("One");
                                myList.Add("Two");
                                myList.Add("Three");
                    
var results = from value in myList select new { value };
                 
You can use the Cast Operator in such cases. The modified code snippet below shows you how to use that.

LINQ CODE
ArrayList myList = new ArrayList();
              myList.Add("One");
              myList.Add("Two");
              myList.Add("Three");
var results = from value in myList.Cast<string>()   select new { value };
                 
  I hope these ten samples helped you learn something new and enjoy reading.

References

Related Articles