Advanced SharePoint
2010 and 2013 Web Part
Development




Rob Windsor
rwindsor@portalsolutions.net
@robwindsor
About Me
•   Senior SharePoint Architect with Portal Solutions
•   Technical Contributor to the Pluralsight On-Demand Library
•   Microsoft MVP, MCPD, MCT
•   Founder and Past-President of the North Toronto .NET UG
•   Co-author of Prof. Visual Basic 2012 and .NET 4.5 (Wrox)
Session Prerequisites
• Experience developing for SharePoint
• Experience building Web Parts
Agenda
•   Visual Web Parts
•   Persistent Web Part Properties
•   Editor Parts
•   Connectable Web Parts
•   Web Part Verbs
•   Asynchronous Web Parts
•   Web Part Gallery
•   Web Part Pages
Visual Web Parts
• Visual web parts traditionally combine a web part with a
  user control
• User controls have full design experience in Visual Studio
• User interface and code behind defined in user control
• Web part “injects” user control dynamically using
  Page.LoadControl
 private const string _ascxPath = @"~/_CONTROLTEMPLATES/.../MyUserControl.ascx";

 protected override void CreateChildControls()
 {
     Control control = Page.LoadControl(_ascxPath);
     Controls.Add(control);
 }
Web Parts in Sandboxed Solutions
• Split page rendering
    Page code runs in ASP.NET worker process
    Sandboxed web part code runs in sandbox worker process
    HTML markup and JavaScript from two worker processes merged
• Sandbox restrictions
      Reduced set of server object model API
      Restricted access outside SharePoint
      No elevation of permissions
      Cannot deploy files to SharePoint system folders
      Must be ASP.NET web parts
      Can only use ASP.NET controls
      No web part connections
Sandbox Visual Web Part Template
• Native visual web part template not compatible
  with sandboxed solutions
   Attempts to deploy user control to system folders
• Visual Studio 2010 Power Tools introduced a
  sandbox compatible template
   No user control
   Designer makes web part behave like a user control
   Markup in user control converted to code at design time
• Visual Studio 2012 only has this template
DEMO
Visual Web Parts
Web Part Properties
• Web Parts support persistent properties
• Configure properties via attributes
    Personalizable(param)
       Directs SharePoint to persist property value
       Parameter indicates if property may be personalized
    WebBrowsable(true)
       Directs SharePoint to generate interface to edit property
    WebDisplayName, WebDescription
       The prompt and tooltip that accompany the data entry element
    Category
       The group in which the properties will be shown

             [Personalizable(PersonalizationScope.Shared)]
             [WebBrowsable(true)]
             [WebDisplayName("Year")]
             [Category("Pluralsight")]
             public int Year { get; set; }
DEMO
Web Part Properties
Cross Site Script Safeguards
• Added in SharePoint 2010
• Indicates developer has taken steps to ensure code is safe
  against scripting attacks
• Two key pieces
    SafeAgainstScript attribute of SafeControl entry
    RequiresDesignerPermission attribute
• Contributors can only set web part properties if:
    SafeAgainstScript is true (not the default)
    RequiresDesignerPermission is false (default)
DEMO
Cross Site Script
Safeguards
Editor Parts
• Editor parts enable user customization
• Editor parts contained within an editor zone
• ASP.NET supplies standard editor parts
     Layout, appearance, etc
• Developers can create custom editor parts
     Similar development experience to Web Part
     Control over interface used to edit properties
     Ability to validate user input
• In web part
     Override CreateEditorParts
• In editor part
     Override CreateChildControls, SyncChanges and
      ApplyChanges
DEMO
Editor Parts
Creating Connectable Web Parts
• Pass data from one web part to another
• Loosely-coupled connection
    Communication managed by WebPartManager
    Provider web part supplies data
    Consumer web parts retrieve data
• Interface used to define data contract
    ASP.NET has standard connection contracts
       Shown later in this module
    Can use custom connection contracts
• SharePoint provides user interface elements to establish
  connections
• Not compatible with sandboxed solutions
DEMO
Web Part
Connections
Web Part Connections using Ajax
• Communication between web parts requires a postback
• Generally, only consumer web part needs to be updated
• Can use partial page rendering (UpdatePanel) to only
  update consumer
• Problem:
    Event triggered by provider
    UpdatePanel in consumer
• Solution:
    Pass reference to control that triggers update from provider to consumer
    Consumer registers control as AsyncPostbackControl with ScriptManager
DEMO
Web Part Connections
Using Ajax
Web Part Verbs

• Add additional menu options to
  dropdown at top-right of Web Part
• Can be handled client-side, server-
  side or both.
Web Part Verbs
  public override WebPartVerbCollection Verbs
  {
      get
      {
          var verbs = new List<WebPartVerb>();

          var verb1 = new WebPartVerb(this.ID + "_ClientSideRssOpenerVerb",
              string.Format("window.open('{0}','RSSXML')", this.FeedUrl));
          verb1.Description = "Open RSS Feed in an external window";
          verb1.Text = "Open RSS Feed";
          verbs.Add(verb1);

          var verb2 = new WebPartVerb(this.ID + "_ServerSideRssOpenerVerb",
              new WebPartEventHandler(ServerSideVerbHandler));
          verb2.Description = "Load the RSS Source Feed.";
          verb2.Text = "View RSS Source Feed";
          verbs.Add(verb2);

          var allverbs = new WebPartVerbCollection(base.Verbs, verbs);
          return allverbs;
      }
  }
DEMO
Web Part Verbs
Asynchronous Web Parts
• Long running tasks are blocking calls
   One web part can bring a page to a crawl
   When on the same page, multiple instances can kill the
    user experience
• Make long running tasks asynchronous
   Don’t hold up page processing
Asynchronous Web Parts
 protected void Page_PreRender(object sender, EventArgs e) {
     Page.RegisterAsyncTask(
         new PageAsyncTask(
             new BeginEventHandler(BeginFeed),
             new EndEventHandler(EndFeed),
             new EndEventHandler(TimoutFeed),
             null, true));
 }

 public IAsyncResult BeginFeed(object sender, EventArgs e, AsyncCallback cb, object state) {
     _feedCaller = GetFeed;
     return _feedCaller.BeginInvoke(cb, state);
 }

 public void EndFeed(IAsyncResult ar) {
     var feed = _feedCaller.EndInvoke(ar);

     var posts = from item in feed.Descendants("item")
                 select new
                 {
                     Title = item.Element("title").Value,
                     Description = item.Element("description").Value,
                     Published = DateTime.Parse(item.Element("pubDate").Value)
                 };
     posts = posts.Skip(_pageNum * _hostPart.PageSize).Take(_hostPart.PageSize);

     FeedListView.DataSource = posts.ToList();
     FeedListView.DataBind();
 }
DEMO
Async Web Parts
Cleaning the Web Part Gallery
• Files provisioned into Content DB do not get
  removed on Feature deactivation
   This includes webpart / dwp files added to Web Part
    Gallery
• Deletion of files can be done in Feature receiver
   Examine element manifests to find web parts
   Remove from web part gallery
Cleaning the Web Part Gallery
 public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
 {
     var site = properties.Feature.Parent as SPSite;
     if (site == null) return;

     var parts = new List<string>();
     var elements = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture);
     foreach (SPElementDefinition element in elements) {
         if (element.ElementType != "Module") continue;

         var node = element.XmlDefinition;
         if (node.Attributes["Url"].Value != "_catalogs/wp") continue;

         foreach (XmlElement childNode in node.ChildNodes) {
             if (childNode.Name == "File") {
                 parts.Add(childNode.GetAttribute("Url"));
             }
         }
     }

     var web = site.RootWeb;
     var gallery = web.Lists["Web Part Gallery"];
     var items = gallery.Items;

     for (int i = items.Count - 1; i >= 0; i--) {
         var item = items[i];
         if (parts.Contains(item.File.Name))
         {
             item.Delete();
         }
     }
 }
DEMO
Cleaning the Web
Part Gallery
Creating Web Part Page Templates
• Create a site page
• Set base type to
  Microsoft.SharePoint.WebPartPages.WebPartPage
• Add one or more web part zones to page
• Provision page instances using Module
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<!-- Other register directives -->
<%@ Register Tagprefix="WebPartPages"
    Namespace="Microsoft.SharePoint.WebPartPages"
    Assembly="Microsoft.SharePoint, Version=14.0.0.0, …" %>

<%@ Page Language="C#"
    Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage"
    MasterPageFile="~masterurl/default.master" %>

<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <WebPartPages:WebPartZone
        ID="MainZone" runat="server"
        FrameType="TitleBarOnly"
        Title="Main Web Part Zone" />
</asp:Content>
Adding Web Parts to Web Part Pages
• Use SPLimitedWebPartManager
     Get reference from property of Page object
• Use SPLimitedWebPartManager.AddWebPart to add
var page = web.GetFile("SiteAssets/Test02.aspx");
using (var manager = page.GetLimitedWebPartManager(
    PersonalizationScope.Shared)) {
    if (!manager.WebParts.Contains(webPartTitle))
    {
        var part = new MostPopularProducts2.MostPopularProducts2();
        part.Title = "Most Popular Products";
        part.Category = "Condiments";
        part.Year = 1997;
        manager.AddWebPart(part, "Left", 0);
    }
}


        Note: Contains method shown in code sample is a custom extension
DEMO
Creating Web Part
Pages and Adding
Web Parts
Additional Stuff
• Closing versus deleting web parts
   Closing a web part does not remove it from page
   Having many closed web parts on a page can degrade
    performance
   Set AllowClose to false to remove option to close from
    web part verbs
• Versioning
   DO NOT change the assembly version of your
    assemblies
   SharePoint stores the full name with version of all web
    parts in galleries and on pages
   Use the AssemblyFileVersion instead
Thank You
• Big thanks to the organizers, sponsors and you for making
  this event possible
• Please fill out your evaluation
• Please keep in touch


    rwindsor@portalsolutions.net
    @robwindsor
    msmvps.com/blogs/windsor

Advanced SharePoint 2010 and 2013 Web Part Development by Rob Windsor - SPTechCon

  • 1.
    Advanced SharePoint 2010 and2013 Web Part Development Rob Windsor rwindsor@portalsolutions.net @robwindsor
  • 2.
    About Me • Senior SharePoint Architect with Portal Solutions • Technical Contributor to the Pluralsight On-Demand Library • Microsoft MVP, MCPD, MCT • Founder and Past-President of the North Toronto .NET UG • Co-author of Prof. Visual Basic 2012 and .NET 4.5 (Wrox)
  • 3.
    Session Prerequisites • Experiencedeveloping for SharePoint • Experience building Web Parts
  • 4.
    Agenda • Visual Web Parts • Persistent Web Part Properties • Editor Parts • Connectable Web Parts • Web Part Verbs • Asynchronous Web Parts • Web Part Gallery • Web Part Pages
  • 5.
    Visual Web Parts •Visual web parts traditionally combine a web part with a user control • User controls have full design experience in Visual Studio • User interface and code behind defined in user control • Web part “injects” user control dynamically using Page.LoadControl private const string _ascxPath = @"~/_CONTROLTEMPLATES/.../MyUserControl.ascx"; protected override void CreateChildControls() { Control control = Page.LoadControl(_ascxPath); Controls.Add(control); }
  • 6.
    Web Parts inSandboxed Solutions • Split page rendering  Page code runs in ASP.NET worker process  Sandboxed web part code runs in sandbox worker process  HTML markup and JavaScript from two worker processes merged • Sandbox restrictions  Reduced set of server object model API  Restricted access outside SharePoint  No elevation of permissions  Cannot deploy files to SharePoint system folders  Must be ASP.NET web parts  Can only use ASP.NET controls  No web part connections
  • 7.
    Sandbox Visual WebPart Template • Native visual web part template not compatible with sandboxed solutions  Attempts to deploy user control to system folders • Visual Studio 2010 Power Tools introduced a sandbox compatible template  No user control  Designer makes web part behave like a user control  Markup in user control converted to code at design time • Visual Studio 2012 only has this template
  • 8.
  • 9.
    Web Part Properties •Web Parts support persistent properties • Configure properties via attributes  Personalizable(param)  Directs SharePoint to persist property value  Parameter indicates if property may be personalized  WebBrowsable(true)  Directs SharePoint to generate interface to edit property  WebDisplayName, WebDescription  The prompt and tooltip that accompany the data entry element  Category  The group in which the properties will be shown [Personalizable(PersonalizationScope.Shared)] [WebBrowsable(true)] [WebDisplayName("Year")] [Category("Pluralsight")] public int Year { get; set; }
  • 10.
  • 11.
    Cross Site ScriptSafeguards • Added in SharePoint 2010 • Indicates developer has taken steps to ensure code is safe against scripting attacks • Two key pieces  SafeAgainstScript attribute of SafeControl entry  RequiresDesignerPermission attribute • Contributors can only set web part properties if:  SafeAgainstScript is true (not the default)  RequiresDesignerPermission is false (default)
  • 12.
  • 13.
    Editor Parts • Editorparts enable user customization • Editor parts contained within an editor zone • ASP.NET supplies standard editor parts  Layout, appearance, etc • Developers can create custom editor parts  Similar development experience to Web Part  Control over interface used to edit properties  Ability to validate user input • In web part  Override CreateEditorParts • In editor part  Override CreateChildControls, SyncChanges and ApplyChanges
  • 14.
  • 15.
    Creating Connectable WebParts • Pass data from one web part to another • Loosely-coupled connection  Communication managed by WebPartManager  Provider web part supplies data  Consumer web parts retrieve data • Interface used to define data contract  ASP.NET has standard connection contracts  Shown later in this module  Can use custom connection contracts • SharePoint provides user interface elements to establish connections • Not compatible with sandboxed solutions
  • 16.
  • 17.
    Web Part Connectionsusing Ajax • Communication between web parts requires a postback • Generally, only consumer web part needs to be updated • Can use partial page rendering (UpdatePanel) to only update consumer • Problem:  Event triggered by provider  UpdatePanel in consumer • Solution:  Pass reference to control that triggers update from provider to consumer  Consumer registers control as AsyncPostbackControl with ScriptManager
  • 18.
  • 19.
    Web Part Verbs •Add additional menu options to dropdown at top-right of Web Part • Can be handled client-side, server- side or both.
  • 20.
    Web Part Verbs public override WebPartVerbCollection Verbs { get { var verbs = new List<WebPartVerb>(); var verb1 = new WebPartVerb(this.ID + "_ClientSideRssOpenerVerb", string.Format("window.open('{0}','RSSXML')", this.FeedUrl)); verb1.Description = "Open RSS Feed in an external window"; verb1.Text = "Open RSS Feed"; verbs.Add(verb1); var verb2 = new WebPartVerb(this.ID + "_ServerSideRssOpenerVerb", new WebPartEventHandler(ServerSideVerbHandler)); verb2.Description = "Load the RSS Source Feed."; verb2.Text = "View RSS Source Feed"; verbs.Add(verb2); var allverbs = new WebPartVerbCollection(base.Verbs, verbs); return allverbs; } }
  • 21.
  • 22.
    Asynchronous Web Parts •Long running tasks are blocking calls  One web part can bring a page to a crawl  When on the same page, multiple instances can kill the user experience • Make long running tasks asynchronous  Don’t hold up page processing
  • 23.
    Asynchronous Web Parts protected void Page_PreRender(object sender, EventArgs e) { Page.RegisterAsyncTask( new PageAsyncTask( new BeginEventHandler(BeginFeed), new EndEventHandler(EndFeed), new EndEventHandler(TimoutFeed), null, true)); } public IAsyncResult BeginFeed(object sender, EventArgs e, AsyncCallback cb, object state) { _feedCaller = GetFeed; return _feedCaller.BeginInvoke(cb, state); } public void EndFeed(IAsyncResult ar) { var feed = _feedCaller.EndInvoke(ar); var posts = from item in feed.Descendants("item") select new { Title = item.Element("title").Value, Description = item.Element("description").Value, Published = DateTime.Parse(item.Element("pubDate").Value) }; posts = posts.Skip(_pageNum * _hostPart.PageSize).Take(_hostPart.PageSize); FeedListView.DataSource = posts.ToList(); FeedListView.DataBind(); }
  • 24.
  • 25.
    Cleaning the WebPart Gallery • Files provisioned into Content DB do not get removed on Feature deactivation  This includes webpart / dwp files added to Web Part Gallery • Deletion of files can be done in Feature receiver  Examine element manifests to find web parts  Remove from web part gallery
  • 26.
    Cleaning the WebPart Gallery public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { var site = properties.Feature.Parent as SPSite; if (site == null) return; var parts = new List<string>(); var elements = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture); foreach (SPElementDefinition element in elements) { if (element.ElementType != "Module") continue; var node = element.XmlDefinition; if (node.Attributes["Url"].Value != "_catalogs/wp") continue; foreach (XmlElement childNode in node.ChildNodes) { if (childNode.Name == "File") { parts.Add(childNode.GetAttribute("Url")); } } } var web = site.RootWeb; var gallery = web.Lists["Web Part Gallery"]; var items = gallery.Items; for (int i = items.Count - 1; i >= 0; i--) { var item = items[i]; if (parts.Contains(item.File.Name)) { item.Delete(); } } }
  • 27.
  • 28.
    Creating Web PartPage Templates • Create a site page • Set base type to Microsoft.SharePoint.WebPartPages.WebPartPage • Add one or more web part zones to page • Provision page instances using Module <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <!-- Other register directives --> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, …" %> <%@ Page Language="C#" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage" MasterPageFile="~masterurl/default.master" %> <asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server"> <WebPartPages:WebPartZone ID="MainZone" runat="server" FrameType="TitleBarOnly" Title="Main Web Part Zone" /> </asp:Content>
  • 29.
    Adding Web Partsto Web Part Pages • Use SPLimitedWebPartManager  Get reference from property of Page object • Use SPLimitedWebPartManager.AddWebPart to add var page = web.GetFile("SiteAssets/Test02.aspx"); using (var manager = page.GetLimitedWebPartManager( PersonalizationScope.Shared)) { if (!manager.WebParts.Contains(webPartTitle)) { var part = new MostPopularProducts2.MostPopularProducts2(); part.Title = "Most Popular Products"; part.Category = "Condiments"; part.Year = 1997; manager.AddWebPart(part, "Left", 0); } } Note: Contains method shown in code sample is a custom extension
  • 30.
    DEMO Creating Web Part Pagesand Adding Web Parts
  • 31.
    Additional Stuff • Closingversus deleting web parts  Closing a web part does not remove it from page  Having many closed web parts on a page can degrade performance  Set AllowClose to false to remove option to close from web part verbs • Versioning  DO NOT change the assembly version of your assemblies  SharePoint stores the full name with version of all web parts in galleries and on pages  Use the AssemblyFileVersion instead
  • 32.
    Thank You • Bigthanks to the organizers, sponsors and you for making this event possible • Please fill out your evaluation • Please keep in touch rwindsor@portalsolutions.net @robwindsor msmvps.com/blogs/windsor