Sie sind auf Seite 1von 27

Module 1: Getting Started Building Web Parts in SharePoint 2010

Benefits of Developing Webparts for SharePoint 2010


Web Parts are reusable and can be used on multiple pages or sites, they can be easily added to a SharePoint webpage from the standard SharePoint interface and their development and deployment is supported in Visual studio 2010, standard web parts do not. Visual Web part in SharePoint 2010 Visual Webparts are ascx user controls that can be added directly to a SharePoint page. One significant enhancement is that Visual studio 2010 manages packing and deployment of these controls Deployment of Visual web part Visual Webparts are deployed directly from Visual studio 2010 by right clicking the project and choosing deploy. Standard Webparts in SP2010 Standard web parts are the classes that inherit from ASP.NET web part base class. When using SPSite SPWeb object in your web part code you should always call Dispose () method of the object to ensure the underlying COM object is destroyed explicitly, or instantiate the SPSite or SQPWeb in a Using statement. You should override the CreateChildControls () method when creating a standard web part. The SPGridView Control provides a simple approach to displaying SharePoint data on a Webpage.

Module 1: Code Snippets: Getting Started: Building Web Parts in SharePoint 2010
5

The following code shows how to modify the Text property of a label when a Visual Web Part loads. NOTE: This code assumes there is an ASP.NET Label control called message in the Visual Web Part
using using using using System; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.WebControls.WebParts;

namespace BonnevilleTestBed.VisualWebPart1 { public partial class VisualWebPart1UserControl : UserControl { protected void Page_Load(object sender, EventArgs e) { message.Text = "Welcome to SharePoint 2010 Development"; } } }

The following code shows how to render a welcome message when a standard Web Part loads:
using using using using using using using using System; System.ComponentModel; System.Runtime.InteropServices; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.WebControls.WebParts; Microsoft.SharePoint; Microsoft.SharePoint.WebControls;

namespace BonnevilleTestBed.BonnevilleStandardWP { [ToolboxItemAttribute(false)] public class BonnevilleStandardWP : WebPart { public BonnevilleStandardWP() { } protected override void CreateChildControls() { //Get the currently logged-on user's name from the SharePoint object model string username = SPContext.Current.Web.CurrentUser.LoginName; LiteralControl myMessage = new Literalcontrol("<H3>Welcome " + userName + " to SharePoint 2010 Development</H3>"); this.Controls.Add(myMessage); base.CreateChildControls(); } protected override void RenderContents(HtmlTextWriter writer) { base.RenderContents(writer); }

} }

The following code shows how to iterate through all lists and subwebs in a SharePoint site, and add them to a treeview control in a Visual Web Part. Note: This code assumes there is a TreeView control called siteStructure in the Visual Web Part. Note also how the addWebs() method is called recursively.
using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; using System.Web; namespace BonnevilleTestBed.Bonneville { public partial class BonnevilleUserControl : UserControl { protected void Page_Load(object sender, EventArgs e) { SPWeb thisWeb = null; TreeNode node; thisWeb = SPContext.Current.Web; //Add the Web's title as the display text for the tree node, and add the URL as the NavigateUri node = new TreeNode(thisWeb.Title, null, null, thisWeb.Url, "_self"); //The Visual Web Part has a treeview control called siteStructure siteStructure.Nodes.Add(node); //Get a reference to the current node, so child nodes can be added in the correct position TreeNode parentNode = node; //Iterate through the Lists collection of the Web foreach (SPList list in thisWeb.Lists) { if (!list.Hidden) { node = new TreeNode(list.Title, null, null, list.DefaultViewUrl, "_self"); parentNode.ChildNodes.Add(node); } } foreach (SPWeb childWeb in thisWeb.Webs) { //Call our own helper function for adding each child Web to the tree addWebs(childWeb, parentNode);

childWeb.Dispose(); } siteStructure.CollapseAll(); }

void addWebs(SPWeb web, TreeNode parentNode) { TreeNode node; node = new TreeNode(web.Title, null, null, web.Url, "_self"); parentNode.ChildNodes.Add(node); parentNode = node; foreach (SPList list in web.Lists) { if (!list.Hidden) { node = new TreeNode(list.Title, null, null, list.DefaultViewUrl, "_self"); parentNode.ChildNodes.Add(node); } } foreach (SPWeb childWeb in web.Webs) { //Call the addWebs() function from itself (i.e. recursively) //to add all child webs until there are no more to be added addWebs(childWeb, parentNode); } } } }

Module 2: What Developers Need to Know About SharePoint 2010?


SharePoint 2010 is based on ASP.NET 3.5 and runs on 64 bit platforms only. The _layouts location is a virtual web folder that points to file system folder on the SharePoint server. Visual studio 2010 provides support for deploying items to the _layouts folder. WSP files simplify deployment across multiple servers in a farm and provide for a standard way for visual studio to open and modify functionality.

Site events enable a developer to capture events such as site deletion site provisioning, or site moving, either just before or after these operation have taken place. Visual studio 2010 and SharePoint 2010 combine to provide full debugging interface for developers. SPWeb, SPSite and SPFarm are objects in SharePoint hierarchy. SPFarm object provides access to all of the services and web applications in a SharePoint deployment. SharePoint object hierarchy order from the highest to most specific: SPFarm, SPWebapplication, SPSite, and SPWeb.

Module 2 - Code Snippets: What Developers Need to Know About SharePoint 2010

The following code shows two event handlers: - The first one (FieldAdded) updates existing list items when a field is added to a list. - The second handler (ListDeleting) prevents the deletion of a list.
namespace ProductMarketing.ProductTaskEvents { public class ProductTaskEvents : SPListEventReceiver { public override void FieldAdded(SPListEventProperties properties) { SPField newField = properties.Field; Guid fieldID = newField.Id; if (newField.Type == SPFieldType.Text) { SPList thisList = properties.List; foreach (SPListItem item in thisList.Items) { item[fieldID] = "Please update this existing item..."; item.Update(); } } base.FieldAdded(properties); } public override void ListDeleting(SPListEventProperties properties) { properties.ErrorMessage = "This list is critical to the marketing campaign and cannot be deleted."; properties.Cancel = true; } } }

The following event handler shows how to update properties of a SharePoint Web site when a new Web is created

namespace ProductMarketing.ProductMarketingWebEvents { public class ProductMarketingWebEvents : SPWebEventReceiver { public override void WebProvisioned(SPWebEventProperties properties) { SPWeb thisNewWeb = properties.Web; thisNewWeb.AllowUnsafeUpdates = true; thisNewWeb.Title = "Updated in Code"; thisNewWeb.Update(); thisNewWeb.AllowUnsafeUpdates = false; base.WebProvisioned(properties); } } }

The following code shows how to enumerate the alerts in a SharePoint site, and also how to enable or disable alerts. Note: This code is designed to run on an application page that includes: - An ASP.NET Label control called alertCount - An ASP.NET button that includes a Click event handler set to the EnableAll funtion - An ASP.NET button that includes a Click event handler set to the DisableAll funtion
namespace Alerter.Layouts.Alerter { public partial class Alerts : LayoutsPageBase { protected void Page_Load(object sender, EventArgs e) { int enabled = 0; int disabled = 0; SPWeb thisWeb = SPContext.Current.Web; foreach (SPAlert alrt in thisWeb.Alerts) { if (alrt.Status == SPAlertStatus.On) { enabled++; } if (alrt.Status == SPAlertStatus.Off) { disabled++; } } alertCount.Text = "Enabled Alerts: " + enabled.ToString() + "\nDisabled Alerts" + disabled.ToString(); } protected void EnableAll(object sender, EventArgs e) {

SPWeb thisWeb = SPContext.Current.Web; foreach (SPAlert alrt in thisWeb.Alerts) { alrt.Status = SPAlertStatus.On; alrt.Update(); } } protected void DisableAll(object sender, EventArgs e) { SPWeb thisWeb = SPContext.Current.Web; foreach (SPAlert alrt in thisWeb.Alerts) { alrt.Status = SPAlertStatus.Off; alrt.Update(); } } } }

The following code creates a new SharePoint site (SPWeb object):


SPSite thisSite = SPContext.Current.Site; thisSite.RootWeb.AllowUnsafeUpdates = true; SPWeb hrWeb = thisSite.RootWeb.Webs.Add("HRWeb", "Human Resources Web", "For use by HR Employees", 1033, "STS#0", false, false); hrWeb.Dispose(); thisSite.RootWeb.AllowUnsafeUpdates = false;

The following code enumerates all of the services provided by the current farm's SPFarm object and displays them in a treeview control in an application page. Note: The code relies on there being a tree-view named farmContents in the application page.
namespace Hierarchy.Layouts.Hierarchy { public partial class HierarchyViewer : LayoutsPageBase { protected void Page_Load(object sender, EventArgs e) { SPFarm thisFarm = SPFarm.Local; TreeNode node; farmContent s.Nodes.Clear(); foreach(SPService svc in thisFarm.Services)

{ node = new TreeNode(); node.Text = "(Type=" + svc.TypeName + ") " + svc.DisplayName; farmContents.Nodes.Add(node); } farmContents.CollapeAll(); } }

The following code enumerates all of the services, web applications, site collections, sites, and lists in a SharePoint farm, and displays them in a treeview control in an application page. Note: The code relies on there being a tree-view named farmContents in the application page. Also note how the addWebs() function is called recursively to ensure sites and subsites are enumerated and displyed in the treeview.
using using using using using System; Microsoft.SharePoint; Microsoft.SharePoint.WebControls; System.Web.UI.WebControls; Microsoft.SharePoint.Administration;

namespace Hierarchy.Layouts.Hierarchy { public partial class HierarchyViewer : LayoutsPageBase { protected void Page_Load(object sender, EventArgs e) { SPFarm thisFarm = SPFarm.Local; TreeNode node; farmContents .Nodes.Clear(); foreach(SPService svc in thisFarm.Services) { node = new TreeNode(); node.Text = "(Type=" + svc.TypeName + ") " + svc.DisplayName; farmContents.Nodes.Add(node); TreeNode svcNode = node; if (svc is SPWebService) { SPWebService webSvc = (SPWebService)svc; foreach (SPWebApplication webApp in webSvc.WebApplications) { node = new TreeNode(); node.Text = webApp.DisplayName; svcNode.ChildNodes.Add(node); TreeNode webAppNode = node; foreach (SPSite site in webApp.Sites) {

try { node = new TreeNode(); node.Text = site.Url; webAppNode.ChildNodes.Add(node); TreeNode siteNode = node; site.CatchAccessDeniedException = false; try { node = new TreeNode(site.RootWeb.Title, null, null, site.RootWeb.Url, "_self"); siteNode.ChildNodes.Add(node); TreeNode parentNode = node; foreach (SPList list in site.RootWeb.Lists) { node = new TreeNode(list.Title, null, null, list.DefaultViewUrl, "_self"); parentNode.ChildNodes.Add(node); } foreach (SPWeb childWeb in site.RootWeb.Webs) { try { addWebs(childWeb, parentNode); } finally { childWeb.Dispose(); } } } catch { } } finally { site.Dispose(); } } } } } farmContents.CollapseAll(); } void addWebs(SPWeb web, TreeNode parentNode)

{ TreeNode node; node = new TreeNode(web.Title, null, null, web.Url, "_self"); parentNode.ChildNodes.Add(node); parentNode = node; foreach (SPList list in web.Lists) { node = new TreeNode(list.Title, null, null, list.DefaultViewUrl, "_self"); parentNode.ChildNodes.Add(node); } foreach (SPWeb childWeb in web.Webs) { try { addWebs(childWeb, parentNode); } finally { childWeb.Dispose(); } } } } }

Module 3: Building Blocks for Web Part Development in SharePoint 2010


SharePoints building blocks enable faster development, proven components, and more efficient code, and they ensure you do not end up building what already exists. The SharePoint Controls section in the Visual Studio toolbox does not display all of the controls available to the developer. To see the complete list type <SharePoint: and the Visual Studio Intellisense will provide a full list.

Module 3 - Code Snippets: Building Blocks for Web Part Development in SharePoint 2010

The following code shows how to use the ListViewByQuery control in a Web Part. Note: The code also includes a CAML query statement that is used by an SPQuery object to set the items to be displayed in the ListViewByQuery control.
protected override void CreateChildControls() { SPWeb thisWeb = SPContext.Current.Web; SPList tasks = thisWeb.Lists["Tasks"];

ListViewByQuery listTasks = new ListViewByQuery(); listTasks.List = tasks; SPQuery taskQuery = new SPQuery(listTasks.List.DefaultView); taskQuery.ViewFields = "<FieldRef Name='Title' /><FieldRef Name='Due' />"; taskQuery.Query = "<Where><Leq><FieldRef Name='Due' /><Value Type='DateTime'>" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now.AddMonths(1)) + "</Value></Leq></Where>"; listTasks.Query = taskQuery; this.Controls.Add(listTasks); base.CreateChildControls(); }

The following code shows how to extract the selected people in a PeopleEditor control. Note: The code runs in a Visual Web Part, and relies on there being a PeopleEditor control named peoplePicker, and an ASP.NET ListBox control called selectedPeople
namespace SharePointControls.ControlExample { public partial class ControlExampleUserControl : UserControl { protected void Page_Load(object sender, EventArgs e) { } protected void getPeople(object sender, EventArgs e) { string allPeople = peoplePicker.CommaSeparatedAccounts; string[] selected = allPeople.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string p in selected) { selectedPeople.Items.Add(p); } } } }

The following code shows how to use the SPGridView control in a Web Part to display list items from a list:
protected override void CreateChildControls() { SPGridView taskGrid = new SPGridView(); taskGrid.AutoGenerateColumns = false; BoundField taskTitle = new BoundField(); taskTitle.DataField = "Title";

taskTitle.HeaderText = "To Do..."; taskGrid.Columns.Add(taskTitle); SPWeb thisWeb = SPControl.GetContextWeb(Context); SPList taskList = thisWeb.Lists["Tasks"]; SPDataSource listSource = new SPDataSource(); listSource.List = taskList; SPDataSourceView view = listSource.GetView(); taskGrid.DataSource = listSource; if (view.CanSort) { taskGrid.AllowSorting = true; } taskGrid.DataBind(); Controls.Add(taskGrid); base.CreateChildControls(); }

Module 4: Accessing SharePoint 2010 Data with Server-Side APIs


Retrive and Manipulate list items in a SharePoint site use SPListItem and SPQuery classes. SPQuery Class makes use of CAML query with a where clause that filters the results that it returns. SPMetal is a Command line tool that creates entities for use with LINQ. LINQ offers early binding to list data, fields and the data types of those fields.LINQ is also a standard approach to querying data. A Content type can be associated with various types of document and completing the additional metadata can improve the management of site data. Some extensions of content type functionality can only be implemented in Visual Studio 2010.

Module 5: Accessing SharePoint 2010 Data with Client-Side APIs


Silverlight, .NET and JavaScript can all use SharePoint Client Object Model. XML and JSON are used to communicate between Client Object Model and SharePoint server.

When the Client Object Model is instantiated the URL to the SharePoint site can be passed to its constructor as a string. Lambda Expressions can be used to filter the items in a list when calling the Lists method on the Client Context load. Silver light applications should query data using an asynchronous background thread.

. Module 5 - Code Snippets: Accessing SharePoint 2010 Data with Client-Side APIs

The following code shows how to use the client object model from a console application. The code first of all lists the Web templates available for a specific Web, and then creates a new Web based on a specific template:
ClientContext clientCtx = new ClientContext("http://intranet.contoso.com"); Site thatSite = clientCtx.Site; clientCtx.Load(thatSite.RootWeb); Web thatWeb = thatSite.RootWeb; WebTemplateCollection templates = thatWeb.GetAvailableWebTemplates(1033, true); clientCtx.Load(templates); clientCtx.ExecuteQuery(); foreach (WebTemplate template in templates) { Console.WriteLine(template.Id + " : " + template.Name + " : " + template.Title); } WebCreationInformation webInfo = new WebCreationInformation(); webInfo.Description = "My client-created Web"; webInfo.Title = "Created by Client OM"; webInfo.Url = "Client3"; webInfo.Language = 1033; webInfo.UseSamePermissionsAsParentSite = true; webInfo.WebTemplate = "MPS#2"; Web newWeb = thatWeb.Webs.Add(webInfo); clientCtx.ExecuteQuery(); clientCtx.Dispose(); Console.WriteLine("Web was created");

The following code shows how to use the client object model from a Windows Presentation Foundation (WPF) application. The code enumerates the lists in a Web, and adds them to a WPF Expander control. Note: The code relies on there being an Expander control named expander1 on the WPF form.
try { ClientContext clientCtx = new ClientContext(siteUrl.Text);

Web thatWeb = clientCtx.Web; clientCtx.Load(thatWeb); clientCtx.Load(thatWeb.Lists); clientCtx.Load(thatWeb, lists => lists.Lists.Where(list => list.Title != null)); clientCtx.ExecuteQuery(); AllLists.Items.Clear (); foreach (Microsoft.SharePoint.Client.List lst in thatWeb.Lists) { AllLists.Items.Add(lst.Title); } clientCtx.Dispose(); } catch (Exception ex) { AllLists.Items.Clear (); AllLists.Items.Add(ex.Message); } expander1.IsExpanded = false;

Note: To see code samples that use the client object model from a Silverlight application, please see:
http://blogs.msdn.com/pandrew/pages/GettingStarted2010Snippets8.aspx

Module 6: Accessing External Data with Business Connectivity Services in SharePoint 2010

SharePoint 2010 provides a new set of technologies known as Business Connectivity Services for retrieving, editing, updating, and deleting data from external systems. This module provides an overview of Business Connectivity Services, and delves into development examples of using Business Connectivity Services data in custom SharePoint solutions.

Business Connectivity Services integrates external content with SharePoint Collaboration and workflow.

SharePoint Designer can be used to build basic Business Connectivity services solutions with many of the features managed by standard out-of box functionality. More Complex requirements can be built in visual Studio 2010.

External Content from Business Connectivity Services can be displayed in the SharePoint web interface and can be taken offline in SharePoint Workspace. Business Connectivity Services enables full data operations including updating and deletion of records to take place if the developer chooses. Both SharePoint Designer and Visual Studio support these actions.

Module 7: Developing Business Processes with SharePoint 2010 Workflows


SharePoint 2010 provides a powerful workflow framework that enables you to implement custom business processes that are driven by SharePoint data. SharePoint 2010 adds Site Workflows to the existing List Workflow capability that was provided in earlier versions. The Workflow engine is based on ASP.NET 3.5 and as well as introducing workflows at Site level, SharePoint 2010 also enables workflows to be built in Visio before being imported into SharePoint Designer or Visual Studio. The Workflow engine supports Sequential and State Machine workflows. The Site Workflow workflows can be started from the Site Actions Menu by clicking the Site Workflows option and then the Site workflow from the Webpage. The Workflow initationForm allows parameters to be provided when a workflow is started.

Module 7 - Code Snippets: Developing Business Processes with SharePoint 2010 Workflows

The following code shows how to return data from a workflow initiation form to the workflow. Note: This code relies on there being an ASP.NET Textbox on the initiation form named MaxPrice. Note also that the code snippet that follows this one uses the data returned.
namespace ApproveRejectProducts.Workflow1 { public partial class GetMaxPrice : LayoutsPageBase {

protected void Page_Load(object sender, EventArgs e) { InitializeParams(); // Optionally, add code here to pre-populate your form fields. } // This method is called when the user clicks the button to start the workflow. private string GetInitiationData() { return (MaxPrice.Text); } } }

The following code shows how to use data returned from a workflow initiation form (as in the above example) and use it in a code activity in a SharePoint 2010 workflow. Note: This code relies on there being a list named Products in the current SharePoint site.
namespace ApproveRejectProducts.Workflow1 { public sealed partial class Workflow1 : SequentialWorkflowActivity { public Workflow1() { InitializeComponent(); } public Guid workflowId = default(System.Guid); public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties(); private void codeActivity1_ExecuteCode(object sender, EventArgs e) { double maxPrice = double.Parse(workflowProperties.InitiationData.ToString()); SPWeb thisWeb = workflowProperties.Web; SPList products = thisWeb.Lists["Products"]; foreach (SPListItem product in products.Items) { if (double.Parse(product["SellingPrice"].ToString()) > maxPrice) { product.ModerationInformation.Comment = "Price too high"; product.ModerationInformation.Status = SPModerationStatusType.Denied; product.Update(); } else {

product.ModerationInformation.Comment = "Price OK"; product.ModerationInformation.Status = SPModerationStatusType.Approved; product.Update(); } } } } }

Module 8: Creating Silver light User Interfaces for SharePoint 2010 Solutions
Silver light 3.0 provides the opportunity for developers to create the next generation of Rich Internet Applications (RIAs). SharePoint 2010 integrates closely with Microsoft Silver light to enable you to build compelling user interfaces that interact with SharePoint data. The SharePoint 2010 Client Object model significantly simplifies the creation of Silver light applications that access SharePoint 2010 sites. Silver light offers a rich user experience and with the code running on the client browser the workload for many operations is removed from the server. SharePoint 2010 supports silver light applications by providing a Silver light Web part that you can add to your page and specify the URL to the Silver light XAP file .If your Silver light application requires additional parameters then you can write your own control to host the Silver light application. A Silver light application can be uploaded to a SharePoint Document Library by an information worker and then added to a page using the built-in Silver light web part in SharePoint 2010,as well as being deployed to the Client Bin folder by an administrator.
Module 8 - Code Snippets: Creating Silverlight User Interfaces for SharePoint 2010 Solutions

The following code shows how to use the SharePoint client object model in a Silverlight application. The code performs the following actions in the Silverlight application: - Obtains a reference to the current SharePoint site in the application's APP.XAML file - Updates a progress bar and status label in real time, based on accessing and retrieving data from SharePoint - Renders media files (images and videos) from SharePoint in the Silverlight application

Note: Silverlight code must call methods of the client object model asynchronously, so that the main UI thread in Silverlight is not blocked while waiting for responses from SharePoint. In this way, the progress bar (and status label) can be updated appropriately. However, because the results from SharePoint are returned on background threads (becuase of the asynchronous nature of the calls) and because updating the UI must be performed back on the main UI thread, the code switches back to the main UI thread by using the Dispatcher.BeginInvoke() calls that you can see below. Also note that the code relies on there being the following controls in the Silverlight User Control: - A Silverlight ProgressBar named Loader - A Silverlight TextBlock named Status - A Silverlight StackPanel named MyContainer
// The following using statements are in the application file (APP.XAML.CS) using Microsoft.SharePoint.Client; using System.Threading;

//The following line of code is in the Startup event for the //Silverlight application in the application file (APP.XAML.CS) ApplicationContext.Init (e.InitParams, SynchronizationContext.Current);

//The following using statements are in a Silverlight user control using Microsoft.SharePoint.Client; using System.Threading; //The following code is in a Silverlight user control ClientContext clientCtx; Microsoft.SharePoint.Client.List docs; int fileTracker = 0; int rowTracker = 0; private void LayoutRoot_Loaded(object sender, RoutedEventArgs e) { Loader.Maximum = 3; Loader.Value = 0; Status.Text = "Connecting to Web..."; clientCtx = new ClientContext(ApplicationContext.Current.Url); clientCtx.Load(clientCtx.Web); clientCtx.ExecuteQueryAsync(updateConnectionStatus, null); } void updateConnectionStatus(Object sender, ClientRequestSucceededEventArgs e)

{ //This method starts on a background thread, but needs to update the progress bar and label in the UI //Therefore, it calls Dispatcher.BeginInvoke() to perform the UI updating on the main thread Dispatcher.BeginInvoke(makeProgressWebConnection); } void makeProgressWebConnection() { //Called by Dispatcher.BeginInvoke() in the function above //The code is now running back on the main UI thread, and so can update the UI Loader.Value++; Status.Text = "Web Connected. Connecting to Lists..."; clientCtx.Load(clientCtx.Web.Lists); clientCtx.ExecuteQueryAsync(updateListStatus, null); } void updateListStatus(Object sender, ClientRequestSucceededEventArgs e) { //This method starts on a background thread, but needs to update the progress bar and label in the UI //Therefore, it calls Dispatcher.BeginInvoke() to perform the UI updating on the main thread Dispatcher.BeginInvoke(makeProgressListConnection); } void makeProgressListConnection() { //Called by Dispatcher.BeginInvoke() in the function above //The code is now running back on the main UI thread, and so can update the UI Loader.Value++; Status.Text = "Lists Connected. Getting List data..."; MyContainer.Children.Clear(); docs = clientCtx.Web.Lists.GetByTitle("Shared Documents"); clientCtx.Load(docs); clientCtx.Load(docs.RootFolder); clientCtx.Load (docs.RootFolder.Files); clientCtx.ExecuteQueryAsync(getListData, null); } void getListData(Object sender, ClientRequestSucceededEventArgs e) { //This method starts on a background thread, but needs to update the progress bar and label in the UI //Therefore, it calls Dispatcher.BeginInvoke() to perform the UI updating on the main thread Dispatcher.BeginInvoke(loadFiles); } private void loadFiles() { //Called by Dispatcher.BeginInvoke() in the function above

//The code is now running back on the main UI thread, and so can update the UI Loader.Maximum = docs.RootFolder.Files.Count; Loader.Value = 0; Status.Text = "Loading Files..."; fileTracker = 0; foreach (File fle in docs.RootFolder.Files) { clientCtx.Load(fle); clientCtx.ExecuteQueryAsync(addFileToUI, null); } } void addFileToUI(Object sender, ClientRequestSucceededEventArgs e) { //This method starts on a background thread, but needs to update the progress bar and label in the UI //It can now also render the files, which is another UI operation //Therefore, it calls Dispatcher.BeginInvoke() to perform the UI updating on the main thread Dispatcher.BeginInvoke(addFile); } StackPanel row = new StackPanel(); void addFile() { //Called by Dispatcher.BeginInvoke() in the function above //The code is now running back on the main UI thread, and so can update the UI string fName = docs.RootFolder.Files[fileTracker].Name; string fUrl = docs.RootFolder.Files[fileTracker].ServerRelativeUrl; fUrl = clientCtx.Url + fUrl; //Simple logic to lay out the files in a three-column configuration if ((rowTracker % 3) == 0) { row = new StackPanel(); row.Orientation = Orientation.Horizontal; MyContainer.Children.Add(row); } if ((fName.EndsWith(".png")) || (fName.EndsWith(".jpg"))) { Image img = new Image(); img.MaxWidth = 100; img.Stretch = Stretch.Uniform; BitmapImage bitMap = new BitmapImage(new Uri(fUrl, UriKind.Absolute)); img.Source = bitMap; HyperlinkButton mediaButton = new HyperlinkButton();

mediaButton.Margin = new Thickness(5); mediaButton.Content = img; mediaButton.TargetName = "_blank"; mediaButton.NavigateUri = new Uri(fUrl); mediaButton.Cursor = Cursors.Hand; row.Children.Add(mediaButton); rowTracker++; } if (fName.EndsWith(".wmv")) { MediaElement media = new MediaElement(); media.MaxWidth = 100; media.Stretch = Stretch.Uniform; media.Source = new Uri(fUrl, UriKind.Absolute); media.AutoPlay = true; HyperlinkButton mediaButton = new HyperlinkButton(); mediaButton.Margin = new Thickness(5); mediaButton.Content = media; mediaButton.TargetName = "_blank"; mediaButton.NavigateUri = new Uri(fUrl); mediaButton.Cursor = Cursors.Hand; row.Children.Add(mediaButton); rowTracker++; } Loader.Value++; fileTracker++; if (fileTracker >= docs.RootFolder.Files.Count) { Status.Text = "All files have now been loaded"; } }

Module 9: Sandboxed Solutions for Web Parts in SharePoint 2010


SharePoint 2010 provides a new sandboxed environment that enables you to run user solutions without affecting the rest of the SharePoint farm. This environment means that users can upload their own custom solutions without requiring intervention from administrators, and without putting the rest of the farm at risk.

Sandboxing provides non-developers and organizations with agility stability and security.

The Sandbox type for a particular solution can be set in the wizard during project creation. It can also be set from the properties window in visual studio when you are developing the project.

The Sandboxed code is run in the context of a specific worker process called SPUCWorkerProcess.The code is then reviewed against a set of allowed objects and methods on the subset of the object model and ,where allowed calls are made against the full object model.

The Sandboxed feature offers advanced resource management that is capable of identifying code that is consuming more resources than acceptable and the reducing the impact of that code by notifying the administrator and if necessary disabling code.

Number of operations is not allowed in sandboxed solution. These include using the SPFarm object and performing asynchronous post backs.

Module 9 - Code Snippets: Sandboxed Solutions for Web Parts in SharePoint 2010

The following example shows code that attempts to run in a sandboxed solutuon. There are four buttons, each of which attempt a different type of action, as follows: - renderWebInfo_Click: This operation will be allowed to run in the sandbox. - renderWebInfoElevated_Click: This operation will not be allowed to run in the sandbox. The sandbox will catch the exception, so the catch{} block will not run. - accessProhibitedNamespace_Click: This operation will not be allowed to run in the sandbox. However, the exception will be caught by the catch{} block. - renderCrossSiteData_Click: This operation will not be allowed to run in the sandbox. The sandbox will catch the exception, so the catch{} block will not run
namespace SBWebPart.SandboxedWebPart { [ToolboxItemAttribute(false)] public class SandboxedWebPart : WebPart { public SandboxedWebPart() { } LiteralControl output; protected override void CreateChildControls() {

Button renderWebInfo = new Button(); renderWebInfo.Text = "Access data in this site"; renderWebInfo.Click += new EventHandler(renderWebInfo_Click); Button renderWebInfoElevated = new Button(); renderWebInfoElevated.Text = "Use elevated privileges"; renderWebInfoElevated.Click += new EventHandler(renderWebInfoElevated_Click); Button accessProhibitedNamespace = new Button(); accessProhibitedNamespace.Text = "Create an HTTP connection "; accessProhibitedNamespace.Click += new EventHandler(accessProhibitedNamespace_Click); Button renderCrossSiteData = new Button(); renderCrossSiteData.Text = "Access data in other site collections"; renderCrossSiteData.Click += new EventHandler(renderCrossSiteData_Click); output = new LiteralControl(); output.Text = ""; this.Controls.Add(output); this.Controls.Add(new LiteralControl("<br />")); this.Controls.Add(renderWebInfo); this.Controls.Add(renderWebInfoElevated); this.Controls.Add(accessProhibitedNamespace); this.Controls.Add(renderCrossSiteData); base.CreateChildControls(); } void renderWebInfo_Click(object sender, EventArgs e) { try { SPWeb thisWeb = SPContext.Current.Web; string message = string.Format("This web contains {0} subwebs", thisWeb.Webs.Count); output.Text = message; } catch(Exception ex) { output.Text = ex.Message; } } void renderWebInfoElevated_Click(object sender, EventArgs e) { try { SPSecurity.RunWithElevatedPrivileges(showWebCount); } catch (Exception ex) { output.Text = "My Caught Error: " + ex.Message;

} } void showWebCount() { SPWeb thisWeb = SPContext.Current.Web; string message = string.Format("This web contains {0} subwebs", thisWeb.Webs.Count); output.Text = message; } void accessProhibitedNamespace_Click(object sender, EventArgs e) { try { System.Net.HttpWebRequest.Create("http://intranet.contoso.com"); output.Text = "Success"; } catch (Exception ex) { output.Text = "My Caught Error: " + ex.Message; } } void renderCrossSiteData_Click(object sender, EventArgs e) { try { SPWeb thisWeb = SPContext.Current.Web; SPSiteDataQuery crossSiteQuery = new SPSiteDataQuery(); crossSiteQuery.Lists = "<Lists ServerTemplate='104' />"; crossSiteQuery.Webs = "<Webs Scope='Recursive' />"; string message = string.Format("There are {0} lists", thisWeb.GetSiteData(crossSiteQuery).Rows.Count.ToString()); output.Text = message; } catch (Exception ex) { output.Text = "My Caught Error: " + ex.Message; } } protected override void RenderContents(HtmlTextWriter writer) { base.RenderContents(writer); } } }

Module 10: Creating Dialogs and Ribbon Controls for SharePoint 2010
SharePoint 2010 provides new user interface components, such as server ribbons, and the new dialog platform. As a developer, you can create controls for the server ribbon and dialog boxes for the dialog platform. Modifying Server Ribbon is supported task in SharePoint 2010. The server ribbon uses AJAX, Dynamic Scaling as well as CSS Layouts, styling and hover effects. The Dialog user interface is a visual interface that helps users maintain context when interacting with content on the SharePoint site. The dialog user interface can be accessed by developers using the HTML elements and JavaScript. The dialog control is typically implemented in an HTML DIV that is made visible programmatically when required.
Module 10 - Code Snippets: Creating Dialogs and Ribbon Controls for SharePoint 2010

The following markup is a simple example of how to add a control to the Site Actions menu. This example adds a menu item that navigates the user directly to the Solutions Gallery, without requiring them to go to the Site Settings page first:
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Id="NewUIActionsMenu" GroupId="SiteActions" Location="Microsoft.SharePoint.StandardMenu" Sequence="1970" Title="Manage Solutions"> <UrlAction Url="/_catalogs/solutions/Forms/AllItems.aspx" /> </CustomAction> </Elements>

The following markup shows how to add a control to the server ribbon. This example adds a 'Help' button to the ribbon in the same group as the built-in 'New Document', 'New Folder', and 'Upload Document' ribbon controls:
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Id="NewUIRibbonControl" RegistrationType="List" RegistrationId="101" Location="CommandUI.Ribbon">

<CommandUIExtension> <CommandUIDefinitions> <CommandUIDefinition Location="Ribbon.Documents.New.Controls._children"> <Button Id="NewUIRibbonControl.ShowHelp" Alt="Help" Sequence="1981" Command="ShowHelp" Image32by32="/_layouts/images/newui/dochelp.png" LabelText="Help" TemplateAlias="o1"/> </CommandUIDefinition> </CommandUIDefinitions> <CommandUIHandlers> <CommandUIHandler Command="ShowHelp" CommandAction="javascript:window.open('http://office.microsoft.com/training/t raining.aspx?AssetID=RC102345091033');" /> </CommandUIHandlers> </CommandUIExtension> </CustomAction> </Elements>

The following code is the source for a Visual Web Part that includes a dialog control that enables the user to change the site title. The JavaScript code uses the client object model to make the changes requested by the user. Note: The code shows good practice by only showing the hyperlink for changing the site title after the client object model has loaded the Web object.
<a href="javascript:showTitleChanger();" href="javascript:showTitleChanger();" id="linkChanger" style="display:none;"> Change Site Title </a> <div id="divEditSiteTitle" style="display:none; padding:5px"> <b>Site Title Changer</b> <input type="text" id="siteTitle" /> <br /> <input type="button" value="Update Site Title" onclick="changeTitle()" /> </div> <SharePoint:ScriptLink ID="showDialog" runat="server" Name="sp.js" Localizable="false" LoadAfterUI="true" /> <script language="ecmascript" type="text/ecmascript"> var clientCtx; var thisWeb; var thisDialog;

_spBodyOnLoadFunctionNames.push("Initialize()"); function Initialize() { clientCtx = SP.ClientContext.get_current(); thisWeb = clientCtx.get_web(); clientCtx.load(thisWeb); clientCtx.executeQueryAsync(onWebLoaded,null); } function onWebLoaded() { var linkChanger = document.getElementById("linkChanger"); linkChanger.style.display = "inline"; } function showTitleChanger() { var divEditSiteTitle = document.getElementById("divEditSiteTitle"); divEditSiteTitle.style.display = "block"; var dialog = { html: divEditSiteTitle, width: 200, height: 200}; thisDialog = SP.UI.ModalDialog.showModalDialog(dialog); } function hideTitleChanger() { thisDialog.close(); } function changeTitle() { thisWeb.set_title(siteTitle.value); thisWeb.update(); clientCtx.executeQueryAsync(onTitleUdated, null); } function onTitleUdated() { hideTitleChanger(); } </script>