Chapter 14. Client-side Programming in Silverlight

WHAT YOU WILL LEARN IN THIS CHAPTER

  • Reading data from SharePoint using Silverlight, CAML, and LINQ

  • Progammatically creating, updating, and deleting list items

  • Modifying the configuration of lists and libraries

  • Managing the files and folders in your site

  • Modifying the Quick Launch and Top Navigation bars

Note

You can do the activities in this chapter with either JavaScript or Silverlight, with the exception of querying the SharePoint Client Object Model using LINQ to Objects. LINQ is only supported in Silverlight via LINQ to Objects. LINQ to SharePoint is only supported with the Server Object Model.

WHY SILVERLIGHT?

Silverlight gives you the ability to build applications rich with functionality and usability far beyond what is possible in JavaScript alone. With Silverlight, you can create C# and VB.Net applications that run in the browser as part of your SharePoint site. Like JavaScript, Silverlight has its own libraries for accessing SharePoint via the Client Object Model. Whether you are using JavaScript or Silverlight, they both communicate with SharePoint via the client.svc web service. The URL for this web service is located at http://yoursiteurl_vti_bin/client.svc where yoursiteurl is the URL of your SharePoint site.

One of the advantages of the Client Object Model is that you can supplement the functionality of the sandbox solutions in SharePoint. In some environments, developers do not need or are restricted from using certain, possibly-unsafe functionality in their SharePoint code. SharePoint addresses these problems by providing a "sandbox" inside which a developer's code can run. This sandbox runs outside of the main SharePoint web application and protects the web site from being unavailable if the developer's code crashes or uses too many server resources. To safely circumvent some of the restrictions of sandbox solutions, you could include JavaScript or Silverlight code that uses the Client Object Model.

Another reason to use Silverlight is its ability to process and display large amounts of data on the screen, and generally, it performs faster than JavaScript. The real trade-off is your ramp-up time to become proficient in Silverlight versus using the JavaScript experience you already have. Now that you have a good understanding of some of the issues and opportunities around using Silverlight inside SharePoint, continue to the next section to get started.

GETTING STARTED

Before you jump in and get busy with Silverlight, you must install a few things:

  • Microsoft Visual Studio 2010

  • Microsoft Silverlight 4 Tools for Visual Studio 2010 http://www.microsoft.com/downloads/details.aspx?FamilyID=40ef0f31-cb95-426d-9ce0-00dcfabf3df5

  • Silverlight Toolkit http://silverlight.codeplex.com—contains many useful, free controls for your Silverlight projects.

  • Microsoft Expression Blend 4 (optional, but recommended)

If you are new to Silverlight development, visit www.silverlight.net/getstarted/ for videos, tutorials, and other resources to get you up and running quickly.

Tip

The Silverlight.net website has many free samples, examples, and tutorials available for your use. If you do not have much experience with Silverlight, doing the tutorials on the website before continuing further in the chapter would be a good idea.

Creating a New Silverlight Application

After you have installed the requisite software, the last thing you need is the Silverlight Client Object Model, which is contained in these two files:

  • Microsoft.SharePoint.Client.Silverlight.dll

  • Microsoft.SharePoint.Client.Silverlight.Runtime.dll

These files are located on your SharePoint server at C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATELAYOUTSClientBin. Copy these files to your local machine because you will need to use them in your Silverlight projects.

To create a new Silverlight application, follow these steps:

  1. Open Visual Studio 2010 from your Start menu, and select File

    Creating a New Silverlight Application
    Figure 14-1

    Figure 14.1. Figure 14-1

    Note

    Depending on which settings you chose when you first opened Visual Studio, your New Project dialog may look different from the one shown in Figure 14-1.

  2. Select Silverlight from the templates on the left, and select Silverlight Application from the list of projects.

  3. Enter a name for your project and click the OK button. The New Silverlight Application dialog shown in Figure 14-2 appears.

  4. Uncheck the "Host the Silverlight application in a new Web Site" checkbox and ensure Silverlight 4 is selected in the Silverlight Version drop-down list. Click the OK button.

    Figure 14-2

    Figure 14.2. Figure 14-2

Note

If you get the message "An update to Microsoft Visual Studio is required to target Silverlight 4" when the project opens, make sure you have installed Microsoft Silverlight 4 Tools for Visual Studio 2010.

After the project is created, the screen shown in Figure 14-3 appears. Notice the Toolbox pane containing the available Silverlight controls on the left side of the screen. Depending on whether you installed the Silverlight Toolkit or controls from a third-party vendor, you may have more or fewer controls.

On the right side of the screen, you see the Solution Explorer pane, which contains the files in the Silverlight project. Underneath the Solution Explorer pane, the Properties pane shows you the properties of the object you have selected in the IDE. When designing controls in Silverlight, you use the Properties pane to configure the controls you use in the project.

The center of the screen contains the Error List pane at the bottom and the design area at the top. The Error List pane displays any errors, warnings, or messages from Visual Studio while you write code and whenever you compile the project. The design area displays the documents you have open. When you open an XAML file, the design area is split into two sections: the WYSIWYG (What You See Is What You Get) designer and the text editor containing the corresponding XML. In the WYSIWYG designer, the Silverlight screens you design in Visual Studio will look the same as when they run in the browser.

Whenever you want to test your code, you must compile it and deploy it to a SharePoint document library. To compile your project, select Build

Figure 14-2

When you compile a Silverlight application project, it creates an XAP file, which contains the code and resources of your project. Any zip file–compatible application can open this XAP file.

Figure 14-3

Figure 14.3. Figure 14-3

The location of the XAP file is located in the BinDebug or BinRelease folder under the folder where your project is located. If you chose to compile your code in Debug mode, your XAP file will be in the BinDebug folder. Otherwise, it will be in the BinRelease folder.

Note

If you compile the project in Debug mode, you can attach Visual Studio to your project and debug the project. The drawback of Debug mode is that the XAP file will be much larger and the code will run slower due to the inclusion of the information Visual Studio needs to allow you to debug your code. When you are satisfied with your project, compile the project in Release mode before you deploy it to production.

Note

You can easily get the location of the XAP file by clicking the Show All Files button in the toolbar of the Solution Explorer pane. The Bin folder will appear, and you can navigate to the XAP file. When you select the XAP file, the Properties pane displays the full path to the file. Copy this path to paste into the upload file dialog in SharePoint.

Adding a Silverlight Web Part to a Web Page

After you have uploaded the XAP file to a document library in your site, you must add your Silverlight control to a web page. SharePoint has a convenient way to display Silverlight controls: the Silverlight Web Part. The Silverlight Web Part allows you to add your Silverlight control to any web part page. To add the Silverlight Web Part to a page, follow these steps:

  1. Navigate to a web part page in your site and select Edit Page from the Site Actions menu to put the page in Edit mode.

  2. Select Web Part from the Insert tab on the ribbon. The web part catalog appears, as shown in Figure 14-4.

    Figure 14-4

    Figure 14.4. Figure 14-4

  3. Choose Media and Content from the Categories list and select Silverlight Web Part from the Web Parts list.

  4. Select the appropriate location from the Add Web Part To drop-down list and click the Add button. The Silverlight Web Part dialog shown in Figure 14-5 appears.

  5. Enter the URL to the XAP file you uploaded earlier and click the OK button. After the web part is added, a page similar to the one shown in Figure 14-6 appears. By default, the web part has a height of 300 pixels and a width of 400 pixels. If your web part is larger than these dimensions, edit the web part's properties and adjust accordingly.

    Figure 14-5

    Figure 14.5. Figure 14-5

    Figure 14-6

    Figure 14.6. Figure 14-6

Note

If your Silverlight application needs initialization parameters configured, you can scroll to the bottom of the web part properties window and put them in the Custom Initialization parameters textbox, shown in Figure 14-7.

Figure 14-7

Figure 14.7. Figure 14-7

Debugging a Silverlight Project

Every now and then, you may need to debug your Silverlight code. You cannot just run your Silverlight project by choosing Debug

Debugging a Silverlight Project
  1. Deploy your XAP file to a document library and add it to a web part page as shown previously in the chapter.

  2. Select Debug

    Debugging a Silverlight Project
    Figure 14-8

    Figure 14.7. Figure 14-8

  3. Choose the "Debug these code types" radio button and ensure that only Silverlight is selected in the list box. This makes Visual Studio load fewer debug symbol files after you attach to your browser.

    Figure 14-9

    Figure 14.8. Figure 14-9

  4. Click OK to return to the Attach to Process dialog shown in Figure 14-8. In the Available Processes list box, select all the processes for your browser where Silverlight is listed in the Type column. If you are using Internet Explorer, look for processes named iexplore.exe. If you are using Firefox, look for processes named firefox.exe.

  5. Click the Attach button. You are ready to debug.

RETRIEVING DATA USING SILVERLIGHT

The code you write to retrieve data in Silverlight is almost the same as the code you write in JavaScript. The main difference is that in JavaScript, you must access the properties of an object by calling set_propertyname and get_propertyname styled methods. In Silverlight, you only need to use the name of the property itself.

As in JavaScript, you must get an instance of the ClientContext class before you can do anything with the Client Object Model. To get the current ClientContext object, call the Current property of the ClientContext class:

ClientContext context = ClientContext.Current;

If you want to get a different ClientContext object, you can use the following code snippet, supplying the full URL of the site:

ClientContext context = new ClientContext(fullsiteurl);

After you get the ClientContext object, you can use the following methods and properties:

  • Site

  • Web

  • ExecuteQueryAsync

You may notice that the names of all properties and methods in the Silverlight Client Object Model are proper cased. One interesting feature of the Client Object Model in Silverlight is that you can use LINQ in a very limited manner to query lists and libraries. Without LINQ, you would write the following code snippet to query the Tasks list:

ClientContext context = ClientContext.Current;
Web site = context.Web;

List tasks = site.Lists.GetByTitle("MyTasks");
this.items = tasks.GetItems(new CamlQuery());

context.Load(this.items);

context.ExecuteQueryAsync(OnSuccess, OnFailure);

You get the list and call the GetItems method, passing in an instance of the CamlQuery class. Notice that a blank CamlQuery class was passed into the method. That just means that SharePoint will return all items from the list. With LINQ, you could write the following code snippet instead:

ClientContext context = ClientContext.Current;
Web site = context.Web;

this.tasks = site.Lists.GetByTitle("MyTasks");
ListItemCollection items = tasks.GetItems(new CamlQuery());


var query = from t in items
      select t;

this.results = context.LoadQuery(query);

context.ExecuteQueryAsync(OnSuccess, OnFailure);

In the code snippet, the LINQ query is highlighted. Essentially, it creates a query that returns all the items in the list. You could add a filter to the query based on one of the built-in properties of the ListItem class. You cannot add a filter on one of the columns in the list, though. Here is an example of using LINQ to return the item whose ID equals 5:

var query = from t in items
      where t.Id == 5
      select t;

After you get your results back from SharePoint, you may be tempted to bind the list of ListItem objects directly to a control like the DataGrid control. That will not work because the list item's field values are actually stored in the ListItem's default property, which is actually a Dictionary object. You cannot bind to a Dictionary object, but you can convert it to something else using LINQ.

To bind to your list items, create a class with similar properties and data types as their parent list. Here is an example for a few columns from a Task list:

public class Task {
  public int Id { get; set; }
  public string Title { get; set; }
  public string Status { get; set; }
  public string Priority { get; set; }
}

With the Task class, you can use LINQ to convert the ListItem objects to Task objects, which you can bind to a control such as the DataGrid control. The following code snippet shows this in action:

var data = from t in this.results
      select new Task {
        Id = t.Id,
        Title = (string)t.FieldValues["Title"],
        Status = (string)t.FieldValues["Status"],
        Priority = (string)t.FieldValues["Priority"]
      };

dataGrid1.ItemsSource = data;

One additional caveat is that Silverlight is multi-threaded, which is great for performance, but it requires you to add some additional code before you can bind your data. All controls in the UI run on the main thread, which is the first thread created when the application starts. When you call SharePoint, the Client Object Model creates a background thread to send the request to SharePoint and wait for a response. After the call succeeds or fails, the corresponding method you passed to the ExecuteQueryAsync method of the ClientContext class executes. The execution occurs on the background thread instead of the main UI thread, and you cannot update the UI from a background thread.

To resolve this problem, you can use a control's Dispatcher property to execute your code and update the UI. The Dispatcher will run the code you give it on the main UI thread. The Dispatcher class has the BeginInvoke method you use to supply the code to execute. You only need to give it the name of a method in your class or an anonymous method. Delivering your code via an anonymous method is faster because you can add your code on the spot instead of creating a new method and passing the method to the BeginInvoke method. The following code snippet shows using an anonymous method with the Dispatcher property:

dataGrid1.Dispatcher.BeginInvoke(delegate() {
  var data = from t in this.results
        select new Task {
          Id = t.Id,
          Title = (string)t.FieldValues["Title"],
Status = (string)t.FieldValues["Status"],
          Priority = (string)t.FieldValues["Priority"]
        };

  dataGrid1.ItemsSource = data;
});

In the code snippet, delegate() {} creates an anonymous method that is passed to the BeginInvoke method of the Dispatcher class. You need only place your UI-updating code between the two curly braces. One neat feature of anonymous methods is that you can still access the local variables and parameters of the method containing this code. In the following activity, you use these classes to query a SharePoint list.

MANAGING LISTS AND LIBRARIES

The Client Object Model also allows you to create, modify, and delete lists and document libraries in your SharePoint site. To get a list of the lists and libraries in a site, you use the Lists property of the Web class. You can also use LINQ to filter the lists and libraries returned from the site by using the following code snippet:

var query = from l in site.Lists
      where !l.Hidden
      select l;

this.listResults = context.LoadQuery(query);

Warning

In general, avoid displaying hidden lists and libraries to the user because modifying them could irreparably break functionality in your site.

In the code snippet, the Lists property is filtered for only the lists and libraries that are not hidden in the browser UI. Afterwards, the LINQ query is passed to the LoadQuery method for retrieval from SharePoint. In the following code snippet, the result of the query from SharePoint is bound directly to a DataGrid control:

listsDataGrid.Dispatcher.BeginInvoke(delegate() {
  listsDataGrid.ItemsSource = listResults;
});

Note that you must still use the Dispatcher property of a control to update it from the background thread that called your OnSuccess method. Unlike the ListItem class, the List class has many useful properties that you can directly bind to. In the following table, you can see some of the most common properties and methods that you will use when dealing with lists and libraries.

The following table displays commonly used List properties:

NAME

DESCRIPTION

AllowContentTypes

If true, the content types associated with the list or library can be managed via the browser.

BaseTemplate

Indicates which list template was used to create the list. A list of common list template types appears later in the chapter.

ContentTypes

The collection of ContentType objects associated with the list.

Created

When the list or library was created.

Description

The description for the list or library.

EnableAttachments

If true, the list supports attaching files to list items. Only applies to lists, not document libraries.

EnableFolderCreation

If true, users can create folders inside the list or library.

Fields

The collection of Field objects in the list.

HasExternalDataSource

If true, the list is an external list.

Hidden

If true, the list does not appear in the browser.

Id

The GUID identifier of the list.

ItemCount

The number of items or documents in the list or library.

LastItemDeletedDate

Specifies the last time a list or document was deleted from the list. This is useful for checking if you need to refresh your data from SharePoint.

LastItemModifiedDate

Specifies the last time the list or its contents was modified. This is useful for checking if you need to refresh your data from SharePoint.

OnQuickLaunch

If true, the list will appear in the Quick Launch bar on the left side of the screen.

RootFolder

The root folder of the list. Use this to get the files and folders in a document library.

Title

The display name of the list.

The following table displays commonly used List methods:

NAME

DESCRIPTION

AddItem

Adds an item to the list.

DeleteObject

Deletes the list permanently.

GetItemById

Gets an item from the list using the item's ID.

GetItems

Gets a collection of items based on the supplied CamlQuery object.

Recycle

Sends the list to the Recycle Bin. This is what happens when you delete a list via the browser.

Update

Saves your changes to the list, which are applied the next time ExecuteQueryAsync is called.

To create a new list or library, you use the ListCreationInformation class. The ListCreationInformation class has various properties you must populate before passing it to the Add method on the Lists collection of the site. At a minimum, you must populate the Title and TemplateType properties as shown in the following code snippet:

ListCreationInformation info = new ListCreationInformation();
info.Title = "My New List";
info.TemplateType = (int)ListTemplateType.Tasks;

site.Lists.Add(info);

context.ExecuteQueryAsync(OnListCreated, OnFailure);

In the code snippet, the new list is named "My New List" and the template type is Tasks. After the ListCreationInformation object is configured, pass it to the Add method on the site's Lists property. After the ExecuteQueryAsync method is called, SharePoint will create the list. Notice that the TemplateType property is set to the ListTemplateType.Tasks enumeration value. You must cast the ListTemplateType enumeration value to the int (integer) data type when setting the value of the TemplateType property. The following table lists the values of the ListTemplateType enumeration and their descriptions:

NAME

LISTTEMPLATETYPE VALUE

Announcements

Announcements

Calendar

Events

Contacts

Contacts

Custom List

GenericList

Discussion Board

DiscussionBoard

Document Library

DocumentLibrary

Form Library

XMLForm

Issue Tracking

IssueTracking

Links

Links

Picture Library

PictureLibrary

Project Tasks

GanttTasks

Survey

Survey

Tasks

Tasks

Wiki Page Library

WebPageLibrary

To modify a list or library, you must call the GetByTitle method of the Lists collection to get the List object. Afterwards, you can modify the list's properties and call the list's Update method to save your changes. To delete a list, call the Recycle method of the list, which sends the list to the Recycle Bin. To permanently delete the list, call the DeleteObject method instead.

Other than managing the items or documents in a list or library, managing the fields in a list or library will be your most common list-related task. The Fields property on the List class returns a collection of field properties that you can use to add new fields, remove fields, or access the properties of the fields themselves. All Field objects have the following properties and methods:

PROPERTY

DESCRIPTION

CanBeDeleted

If true, the field can be removed from the list.

DefaultValue

The default value, if any, for the field.

Description

The description for the field.

FieldTypeKind

The type of field. There is a list of field types later in the chapter.

Filterable

If true, the field can be used to filter the list. Some fields, including "Multiple lines of text" fields, cannot be used as filters.

Hidden

If true, the field does not appear in the browser UI.

Id

The GUID identifier for the field.

InternalName

The original name of the field. The internal name can never be changed after the field is created.

ReadOnlyField

If true, the field is read-only.

Sealed

If true, the field cannot be deleted or modified in any way.

Sortable

If true, the field can be used to sort the list. Some fields, including "Multiple lines of text" fields, cannot be used to sort the list.

Title

The display name of the field.

TypeDisplayName

The display name for the field's type.

METHOD

DESCRIPTION

DeleteObject

Deletes the field permanently from the list.

Update

Saves your changes to the field, which are applied the next time ExecuteQueryAsync is called.

You may have noticed that the previous tables of field properties and methods did not include any of the settings you have used to add a field via the browser. This is because the Field class is the parent or base class of the various classes used to create fields. When you want to add or modify a field in a list, you use one of the following classes that matches the type of your field:

FIELD TYPE

CLASS

INTERNAL TYPE

Single line of text

FieldText

Text

Multiple lines of text

FieldMultiLineText

Note

Choice (menu to choose from)

FieldChoice (multiple choices not allowed) FieldMultiChoice (multiple choices allowed)

Choice

Number (1, 1.0, 100)

FieldNumber

Number

Currency ($, ¥, є)

FieldCurrencyhar

Currency

Date and Time

FieldDateTime

DateTime

Lookup (information already on this site)

FieldLookup

Lookup

Yes/No (checkbox)

Field

Boolean

Person or Group

FieldUser

User

Hyperlink or Picture

FieldUrl

URL

Calculated (calculation based on other columns)

FieldCalculated

Calculated

External Data

Can be any of the Field classes because you choose which field(s) to display in the list.

BusinessData

Managed Metadata

FieldLookup

TaxonomyFieldType

To add a field to a list, you must call the AddFieldAsXml method on the list's Fields collection. The AddFieldAsXml method takes primarily a string parameter with the XML of the field definition and returns a Field object that you can cast to one of the classes in the previous table to configure extra settings. The AddFieldAsXml method also takes a Boolean parameter for adding the field to the list's default view and an AddFieldOptions value to specify additional options for the field. Consider the following code snippet:

Field field = list.Fields.AddFieldAsXml(@"<Field DisplayName='My New Field'
  Type='Note' />", true, AddFieldOptions.DefaultValue);

FieldMultiLineText textField = context.CastTo<FieldMultiLineText>(field);
textField.NumberOfLines = 6;
textField.RichText = true;
textField.Update();

context.ExecuteQueryAsync(OnFieldCreated, OnFailure);

The AddFieldAsXml method is called to create a rich text field using the field XML string with the default options. The field is added to the list and its default view. The AddFieldAsXml method returns a Field object, which is subsequently cast to a FieldMultiLineText object by calling the CastTo<> method on the ClientContext class. The previous table contains a list of the valid values you use for the Type attribute in your field XML.

Using the FieldMultiLineText object, the number of lines and rich text support is configured for the field as in the browser UI. Finally, the Update method is called on the field to save your changes. After the ExecuteQueryAsync method is called, SharePoint adds the field to the list.

To modify a field, you call either the GetByInternalNameOrTitle or GetByTitle method on the Fields property of the list. Afterwards, you can cast it to the appropriate field class as shown in the previous code snippet. When you are finished with your changes, call the Update method on the field and the ExecuteQueryAsync method on the ClientContext class. To delete a field, you call the DeleteObject method on the field. In the next activity, you will use these List and Field classes to display, modify, and create lists in your site.

Warning

There is no Recycle method on the Field class so when you delete the field, it is permanent. When you delete a field, the values for the deleted field in the existing items and documents are permanently deleted, too.

MANAGING FILES AND FOLDERS

In Figure 14-12, you see the virtual file system of SharePoint that appears when you pin the All Files window in SharePoint Designer. Many files and folders do not appear in the UI. At times, you may need to manipulate files and folders using the Client Object Model, especially if you want to upload documents or create folders inside a document library.

Figure 14-12

Figure 14.11. Figure 14-12

In the Client Object Model, folders are represented by the Folder class and files are represented by the File class. Not all files and folders are in a document library but you can still access them using the Client Object Model. You can get a Folder object by using one of the following:

  • Calling the Web class's RootFolder property, which returns the folder at the root of the SharePoint site.

  • Calling the List class's RootFolder property, which returns the folder at the root of the SharePoint list.

  • Calling the Web class's GetFolderByServerRelativeUrl method, passing in the server-relative URL of the folder.

If you already have a Folder object, you can get its parent folder using the ParentFolder property or its subfolders using the Folders property. The Folder class also has a Files property that returns a list of File objects for the files in the folder.

You create a folder by calling the Add method on the Folders property on an existing Folder object, passing in the name of the new folder. The Add method returns a Folder object, which you can use to create subfolders or add files.

To rename a folder, you get the Folder object representing the folder and modify its Name property. Afterwards, you call the Folder object's Update method. To delete a folder, you call the Folder object's Recycle method, which sends the folder to the Recycle Bin. To permanently delete a folder, call the DeleteObject method instead, which also permanently deletes the folder's contents.

The File object represents a file in the virtual file system whether the file is located in a document library or not. The File object is interesting because you can modify its properties, including its name, and you can modify its contents. The File class has the following properties and methods:

PROPERTY

DESCRIPTION

Author

The user who created the file

CheckedOutByUser

The user who has the file checked out

CustomizedPageStatus

Whether the page has been customized or not

Level

Whether the file is checked out, draft, or published

MajorVersion

The major version of the file

MinorVersion

The minor version of the file

ModifiedBy

The user who last modified the file

Name

The name of the file

ServerRelativeUrl

The URL of the file relative to the server name

Title

The display name of the file

Versions

The previous versions of the file

METHOD

DESCRIPTION

CheckIn

Checks in the file.

CheckOut

Checks out the file so nobody else can modify it.

CopyTo

Copies the file to another location.

DeleteObject

Deletes the file permanently.

GetLimitedWebPartManager

Returns a LimitedWebPartManager object that you use to manipulate the web parts on a web part page.

MoveTo

Moves a file.

OpenBinaryDirect

Gets the contents of the file itself.

Publish

Publishes the file for approval.

Recycle

Sends the file to the Recycle Bin.

Method

Description

SaveBinary

Updates the contents of an existing file.

UndoCheckOut

Reverses a checkout and any pending file changes.

UnPublish

If the file is submitted for approval, this method un-submits the file. Otherwise, this method rolls back to the previous major version of the file.

To add a file to a folder, you create a FileCreationInformation object and configure its properties. Afterwards, you call the Add method on the Files property for a Folder object passing in the FileCreationInformation object. The following code snippet shows this in action:

foreach (System.IO.FileInfo file in files) {
  using (System.IO.FileStream fs = file.OpenRead()) {
    byte[] b = new byte[fs.Length];
    fs.Read(b, 0, (int)fs.Length);
    fs.Close();

    FileCreationInformation info = new FileCreationInformation();
    info.Content = b;
    info.Overwrite = false;
    info.Url = file.Name;

    folder.Files.Add(info);
  }
}

context.ExecuteQueryAsync(OnUploadedSuccess, OnFailure);

In the snippet, a foreach loop is used to iterate a list of FileInfo objects that represent files on a workstation. Inside the loop, the OpenRead method is called on the FileInfo object to get a FileStream object and load the file's contents into a byte array. Next, the FileCreationInformation object is created and populated with the file's name and contents. The FileCreationInformation object is also configured to not override an existing file. Finally, the FileCreationInformation object is added to the Folder object's Files property via the Add method. Like everything else in this chapter, you still must call the ExecuteQueryAsync method for SharePoint to process any of these operations.

To modify a file, you loop through the Files property on a folder or, more commonly, call the GetFileByServerRelativeUrl method on the Web class, passing in the server relative URL of the file. With the File object, you can rename it using the Name property, read its contents using the OpenBinaryDirect method, or update its contents using the SaveBinary method. Afterwards, call the Update method to save your changes. With the File and Folder classes, you can create a tree displaying the content and structure of your site as shown in the following activity.

Warning

Calling the Update method on a File object is the same as clicking the Save button in SharePoint Designer when a file is opened in Advanced mode. This causes the file to become customized. For updating files in a document library, this is normal behavior. But using this method to update ASPX or master pages can negatively impact performance, especially on sites with heavy usage.

Note

If you are wondering why you used the HTML Form Web Part instead of the Silverlight Web Part, here is the reason: the Silverlight Web Part configures the Silverlight object tag to run in windowless mode. This allows the web part menu to appear on top of the Silverlight control when the menu is displayed. If the Silverlight object tag were not running in windowless mode, the web part menu would appear behind the Silverlight control the same way an HTML element does when it overlaps space with a listbox or drop-down list. One of the disadvantages of running in windowless mode is that drag-and-drop events are not supported. You still can use the Silverlight Web Part to host the control from this activity, and all the functionality will still work except for dragging and dropping files.

MANAGING NAVIGATION

You can also use the object model to modify the Quick Launch and Top Navigation bars in your site. You access the Quick Launch and Top Navigation bars via the following code snippet:

ClientContext context = ClientContext.Current;
Web site = context.Web;
context.Load(site.Navigation.QuickLaunch);
context.Load(site.Navigation.TopNavigationBar);

context.ExecuteQueryAsync(OnSuccess, OnFailure);

When the OnSuccess method is called, the site.Navigation.QuickLaunch and site.Navigation.TopNavigationBar properties are populated with the NavigationNode objects that correspond to the clickable items on both bars. The NavigationNode object has the following properties and methods:

PROPERTY

DESCRIPTION

Title

The text displayed for the navigation node

Url

The URL for the navigation node's hyperlink

Children

The list of child navigation nodes

METHOD

DESCRIPTION

DeleteObject

Deletes the navigation node and its children

Update

Saves your changes to the navigation node

When you start using the Client Object Model to modify these bars, determining where to put the nodes to make them appear where you want on the screen may be a little difficult. Take a look at Figure 14-14.

In the figure, the Quick Launch bar is organized with Libraries, Lists, and Discussions at the top levels and the individual lists and libraries underneath the appropriate top level. If you look at the tree control for the Quick Launch, you will notice that it matches the structure of the Quick Launch bar except that it does not display any nodes lower than two levels deep. The node named Level3 does not appear at all under Site Pages in the Quick Launch bar.

If you look at the Top Navigation bar, you see these four tabs:

  • Home

  • Level2(Home)

  • Level1

  • Level2

But in the tree control for the Top Navigation bar, you see only the Home and Level1 nodes at the top level. This means that all nodes at levels 1 and 2 will appear as tabs on the Top Navigation bar. Nodes at level 3 will appear as menu items under their parent node's tab. Nodes at levels 4 and below will not appear at all.

Figure 14-14

Figure 14.13. Figure 14-14

To create a navigation node, you must create a NavigationNodeCreationInformation object. The NavigationNodeCreationInformation class has the same properties as the NavigationNode, including the following additional properties:

NAME

DESCRIPTION

IsExternal

If true, the Url property points to a file outside the site. If false, the Url is internal to the site. If the file does not exist and IsExternal is set to false, SharePoint will return an error message.

PreviousNode

Specifies the node after which the new node should be inserted.

AsLastNode

If you set this to true, the node is added at the end of the list. Otherwise, it is added at the beginning of the list if PreviousNode is not specified.

After you have configured the NavigationNodeCreationInformation object, you call the Add method on the Children property of a NavigationNode object or the Add method on the Navigation.QuickLaunch or Navigation.TopNavigation properties of the Web object.

To update a NavigationNode, you will need to programmatically traverse the NavigationNode objects until you get to your target. Then, you can update its properties and call the Update method to save your changes. To delete a NavigationNode, simply call its DeleteObject method. Now that you have been introduced to the Navigation and NavigationNode classes, you can modify your site's navigation by following the steps in the next activity.

LIMITATIONS

No discussion about any functionality this powerful would be complete without covering its limitations. Whether you are using JavaScript or Silverlight, these are some of the limitations you will face:

  • Your code can access any site collection as long as it is in the same SharePoint web application as the one where the code is running.

  • Only Windows, Forms Based, and Anonymous authentication are supported.

  • If you are using Silverlight and the site uses Forms Based Authentication, you must manually change the authentication mode of the ClientContext class and specify a username and password as shown in the following code snippet:

    ClientContext context = ClientContext.Current;
    context.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
    clientContext.FormsAuthenticationLoginInfo =
      new FormsAuthenticationLoginInfo("yourusername", "yourpassword");

    Note

    The username and password are sent in "clear text" and can be viewed by anybody monitoring your server or network traffic. If you must use Silverlight in conjunction with Forms Based Authentication, make sure you secure the site with an SSL certificate to encrypt the traffic between the web server and the user's browser.

  • If you query an external list using the Client Object Model, you must specify the columns to return in your CAML query and the call to the Load method of the ClientContext class. Otherwise, you will get the error message "The given key was not present in the dictionary."

  • If you are using JavaScript with the Client Object Model, you must include the FormDigest control in the master page. By default, this control is already in the site's master pages, but it could be accidently removed or you could create a page that does not use the site's master page.

  • If you intend to update list items or documents in the site, you may need to re-query the list or library before performing your update. Another user may have updated your list item or document after you queried the list or library but before your code tried to execute an update. If that is the case, you will get an error message stating the item or document has been updated since you last retrieved it.

SUMMARY

In this chapter, you have seen how to use Silverlight to greatly extend the functionality of your SharePoint sites. Practically nothing has been taken off the table in terms of what you are able to do in the Client Object Model versus the Server Object Model. With the Client Object Model, your SharePoint sites no longer have to be used out-of-the-box, even if they are hosted by a third party that does not allow the traditional methods of customization used by SharePoint developers. With the techniques you learned in this chapter, you should be able to increase the ROI value of your SharePoint investment by several orders of magnitude.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.183.138