Contents tagged with Web Parts

  • SharePoint 2013 - Introduction to the Minimal Download Strategy (MDS)

    Tags: SharePoint 2013, Web Parts

    Introduction

    SharePoint is based on a very rich web interface containing lots of moving parts and lots of customizable areas. As you know the Interwebz is based on a request-response approach where you request a page and get a response back. The approach is the same whether you update the whole page or portions of it. The last decade we've seen smart approaches working around this "problem" using DHTML, JavaScript, AJAX, UpdatePanels, you name it. Facebook, which also contains a very rich and dynamic interface, has been excellent in making a dynamic web interface minimizing the amount of data downloaded for each user interaction and in this way also increasing the perceived performance.

    Up until now SharePoint (out-of-the-box) has not been that efficient on this, even though SharePoint 2010 did some improvements. Most often the whole page has been reloaded for each and every action, this of course affects all end-users and the perceived performance of SharePoint.

    But now, with SharePoint 2013, we have a whole new paradigm thanks to the Minimal Download Strategy - MDS. In this post I will walk you through some details of MDS, how to leverage it in your own customizations and how to successfully adapt your current and future customizations to MDS.

    Note: this article applies to SharePoint 2013 Preview

    Note: article has been updated per 2012-08-16 with some more nice details..

    The Minimal Download Strategy (MDS) - an overview

    The Minimal Download Strategy is by default enabled on Team sites, Community sites and a few others in SharePoint 2013. Once this feature (and it's also a Feature, notice the capital F, we'll get back to that later) all pages for that site is rendered "through" the /_layouts/15/start.aspx page. This page is responsible for loading pages from the site using the MDS. The start.aspx page has a specific JavaScript object asyncDeltaManager (defined in start.js). Basically it parses the URL, looks for the # sign and takes the path following that and dynamically loads that page.

    A MDS Url

    Subsequent requests to pages are dynamically loaded through the asyncDeltaManager object. Once a link is clicked it will invoke a method in the JavaScript object which creates the MDS URL and appends the query string parameter AjaxDelta=1. A request is created and downloaded asynchronously and only the "delta" is returned to the client and assembled and rendered using JavaScript.

    How does it really work?

    Let's dig one step further down and see what really happens and detail out some of the moving parts.

    Enabling or disabling MDS on a site

    [Edited 2012-08-16] First of all what sites do have the MDS enabled by default? MDS is actually a SharePoint feature (Name; MDSFeature, Id: 87294C72-F260-42f3-A41B-981A2FFCE37A) which is Web scoped. Some of SharePoint 2013 Site Templates has this feature stapled (for instance Team, Community, Wiki, Projects, App and Blog sites). The feature is very straightforward - it toggles the EnableMinimalDownload property of the SPWeb object. So you can quite easily yourself turn it off using code (server side or CSOM!!) or PowerShell. Of course you also use the Site Settings > Site Features to turn it on or off as well.

    The MDS is not enabled on publishing sites and is (as I understand it) not compatible with publishing sites, there are a couple of reasons for this, continue to read for more information

    Requirements for MDS

    Except enabling MDS it is required for the MDS to work there is one control that must be placed in the master page - the AjaxDelta control. It should be added to the head section of the master page. This control is responsible for a couple of things. If the page is a start/home page it will clear all controls and make sure that the page is loaded fully and registers the correct scripts.

    How is the delta pages generated?

    One of the key things in the MDS implementation is that SharePoint 2013 contains a new Page class - the DeltaPage. This page class is the key to generating the full pages or just the deltas. Fortunately the common pages such as WebPartPage, WikiEditPage, UnsecuredLayoutsPageBase, LayoutsPageBase etc are inheriting from this page. so most of the out-of-the box pages works and hopefully your custom application pages as well. This page class is quite smart it can handle when MDS is not enabled (ie default rendering) and when MDS is enabled. When MDS is enabled for the site this page is responsible for creating the delta response. The DeltaPage is also responsible for handling exceptions such as when the master page is different (another one or a new version). Every delta request sent using the asyncDeltaManager has a specific request header - the X-SharePoint header. This header contains information about the master page, the language and if the page is in read-write or read-only mode.

    X-SharePoint

    [Added 2012-08-16] This header is important since it contains the master page, the version of the master page etc and SharePoint uses this to determine weather to do a full reload (if the master page have changed) or not. So if you’re working on a master page, be prepared for full reloads of the page, at least the first time you request a page using the modified master page.

    The PageRenderMode control

    [Added 2012-08-16] There is one control called PageRenderMode that can be used on a master page, web part page or page layout. This control has one property called RenderModeType which can have one of two possible values; Standard or MinimalDownload. If the control is placed on a page and have the property set to Standard – it will prohibit the page from being rendered using MDS. If the control is not present or if it’s property is set to MinimalDownload it can participate in MDS rendering. So this control can be used on specific (master)pages to prohibit MDS.

    <SharePoint:PageRenderMode runat="server" RenderModeType="MinimalDownload" />

    A word of caution here, if you’re using the Design Manager to generate master pages, this control will automatically be inserted into the generated artifacts.

    Another gotcha here is that even if you have the PageRenderMode control set to MinimalDownload whenever the publishing features are enabled and you have the ribbon on the page, specifically when using the PublishingRibbon in your master page, SharePoint will automagically inject, during runtime, the PageRenderMode control with the property set to Standard.

    How does the delta response look like?

    The response returned to the asyncDeltaManager has a specific format which very much resembles how ASP.NET UpdatePanels work. Each control that should be re-rendered on a page has it's HTML rendition and all these renditions are separated by a specific token which has the format:

    -deltaboundary-<Guid>-

    The Guid is unique (which is the purpose of guids :-) and the asyncDeltaManager retrieves the current token from the response header called deltaBoundary.

    This image shows a snippet from the IE Network monitor.

    deltaboundary

    After all deltas, at the end of the response, is another encoded set of data.

    More delta stuff

    This data tells what each delta boundary block is intended for and has the following format:

    content length|type|id|data|

    Type identifies what kind of delta data it is; controlDelta is a standard control, pageTitle the title of the page, pageRedirect a page redirection etc. There are about ten more different types. Id identifies the control identifier and data, is the data...

    The asyncDeltaManager takes all this information and assembles the page, so it all looks fast and neat for the end users.

    MDS compliant controls

    If you upgrade a SharePoint 2010 site with custom Web Parts or controls, you will soon realize that the upgraded Webs are not rendered using MDS - even if you update the EnableMinimalDownload property on the SPWeb object. This is due to the reason that the DeltaPage checks all controls present on the page for a specific attribute - the MdsCompliantAttribute. This is an attribute that you can set on a class or on an assembly. If any of the controls present on a page does not have this attribute or has the IsCompliant property set to false it will not render any delta for that page.

    To make your own controls MDS Compliant the classes should look like this:

    [ToolboxItemAttribute(false)]
    [MdsCompliant(true)]
    public class MDSTest : WebPart
    {
        protected override void CreateChildControls()
        {
            this.Controls.Add(new LiteralControl("MDS is enabled on the site:" + 
                SPContext.Current.Web.EnableMinimalDownload));
        }
    }

    Or, you could add the MdsCompliant to the assembly instead of to each class.

    [Added 2012-08-16] The MdsCompliant attribute is set on the whole Microsoft.SharePoint.dll assembly, but not on the Microsoft.SharePoint.Publishing.dll assembly. This is a bummer. This means that all the Field Controls, used in page layouts, are not MDS compliant – which means no MDS on publishing sites.

    An important thing here to remember is that the MdsCompliant attribute does not work in the Sandbox!!! So adding a Sandboxed Web Part to a page disables MDS for that page, period.

    Summary

    Whew, quite a long introduction to the Minimal Download Strategy. I hope that you have a better understanding of it by now and that you better know how to possibly troubleshoot any issues with it (or rather your customizations on MDS sites). There are more to discuss on this topic though, but we'll save that for another day. Cheers!

  • I'm on the SharePoint Pod Show talking about Web Parts

    Tags: Personal, Web Parts, SharePoint 2010

    The 65th SharePoint Pod Show is out featuring...tada...me :-)

    The SharePoint Pod ShowThe SharePoint Pod Show is THE podcast about SharePoint and is done by Rob Foster, Nick Swan and Brett Lonsdale and has featured a lot of great SharePointers from all around the world throughout the years. If you haven't already listened to the podcasts, then you got 65 episodes to catch up on! There are some epic ones, such as my favorite one #50 - which is about performance tuning. And make sure that you subscribe - you don't want to miss their SPC11 Road-trip...

    This episode was recorded at the MVP Summit earlier this year in Redmond between two sessions. It was my first time meeting most of the MVP's in real life and Rob was the one interviewing me. He's one heck of an interviewer asking questions like an ice-hockey radio commentator in some weird southern accent... It was great fun and we discussed SharePoint development and Web Parts development in particular. We talked through how to get started with SharePoint development, how to build Web Parts and why I wrote my book (SharePoint 2010 Web Parts in Action).

    Until next time.

  • Deploying Web Parts Farm-wide using the WebPartAdderExtension element in SharePoint 2010

    Tags: Web Parts, SharePoint 2010

    Here goes another post using the WebPartAdderExtension Element. I previously wrote an introduction to custom Web Part Gallery sources and a second one on how to enhance the end-user experience when adding new Web Parts. Now I'm going to show you another trick that this technique can be used for.

    Introduction

    Deploying Web Parts are normally done by using the Module element in the Elements manifest and using that element uploading/deploying Web Part Controls Description files (.webpart or .dwp files) into the Web Part catalog. These Element manifests for Web Parts must be scoped to the Site Collection level, since it is there where the Web Part catalog lives (~/site/_catalogs/wp). So if you want do deploy a solution containing a set of Web Parts you need to activate that Feature on each and every Site Collection. You can do it in a number of ways such as Feature Stapling, code, scripting etc. Could be quite tedious work if you have a large farm with many site collections and web applications. Also when retracting solutions with Features that uses Modules we manually have to clean up the files provisioned.

    Enter WebPartAdderExtension!

    So once again our new acquaintance the WebPartAdderExtension can help us in the scenario where we want to deploy Web Parts in a more efficient manner. In the two previous posts I built both examples using Site Collection scoped features - that's the way we normally think when programming for Web Parts. But the good news is that the WebPartAdderExtension element that is used to deploy the custom Gallery Source can actually be scoped to the following scopes:

    • Site - a Site Collection
    • WebApplication - a Web Application
    • Farm - the whole Farm

    Did you see that! Using this simple technique you can easily deploy and maintain Web Parts for a specific Web Application or the whole Farm if you like!

    The WebPartAdderExtension element

    Just follow the previous two guides and change the Scope of your Feature and you're ready to go.

    A word of caution

    It's unsafe  - watch out for zombies!There is one caveat with this though. If you set your Feature to Farm and deploy the solution, but only deploy/install it to one ore more Web Applications. The Safe Controls will only be installed on those specific Web Applications - not on all Web Applications in the farm. But the custom Gallery Source is still visible in the whole farm. This results in that you will get Safe Control errors as soon as you add the Web Part to a page in an Web Application where the Solution is not deployed.

    Summary

    This was the third really cool thing about the Web Part Adder and it's friends. It's never been this easy deploying Web Parts in SharePoint 2010. There are still a few more parts to be disclosed about this little nugget!

  • Improve the experience using Modal Dialogs when adding Web Parts in SharePoint 2010

    Tags: Web Parts, SharePoint 2010

    This is a follow-up post on yesterdays introduction to the WebPartAdder (which lately has been one of my favorite features of SharePoint 2010). In that post I mentioned that you could invoke a JavaScript function when a Web Part is added using a custom Web Part Gallery source.

    The Silverlight Web Part

    The Silverlight Web PartIf you have been working with SharePoint as an end-user you've probably seen the nice modal dialog that pops up when you're adding a Silverlight Web Part to a page, see the image to the right. It allows you to very easily configure the Web Part with the appropriate XAP file without editing the Web Part properties. If more Web Parts were like this it would be a whole lot easier working with Web Parts.

    The good news is that you can do this for your Web Parts - using a custom Gallery Source, just as I showed yesterday. And I'll show you how.

    Create a custom Web Part with a default Modal Dialog property form

    In this sample we're basically building out the same structure as I showed yesterday. I'll show you a bit different approach though - which is a bit more compact. And we'll need to throw in some custom JavaScript and an Application Page as well.

    Create a new Visual Studio project

    The SPIFirst of all create a new empty SharePoint project in Visual Studio. Then add an Empty Element SPI, we'll skip adding a Web Part like yesterdays post showed. In this Empty Element SPI add three files; one for the Web Part, one for the Gallery Source and one for the Gallery Item.

    Make sure to change the Scope of the automatically added Feature to Site Collection, instead of the default Web value!

    Implement the Web Part

    We're completely manually creating the Web Part in this case (my favorite way to do it :-). Add a simple string property (in this case called Data), a default constructor, another constructor that takes the property value as parameter and finally make the UI in the CreateChildControls() method. In order to get it to work you need to manually add a reference to System.Web. It should look something like this:

    public class ScriptedAdderWebPart : WebPart {
    
        public ScriptedAdderWebPart() {
        }
    
        public ScriptedAdderWebPart(string data) {
            Data = data;
        }
    
        protected override void CreateChildControls() {
            this.Controls.Add(new LiteralControl(
                String.Format("You entered: {0}", this.Data)
                ));
            base.CreateChildControls();
        }
    
        [WebBrowsable]
        [Personalizable(PersonalizationScope.Shared)]
        public string Data { get; set; }
    }

    You also need to add the SafeControl entry for this Web Part on the SPI. Right-click the SPI and choose Properties. Click the ellipsis button on the Safe Controls row and click Add to add the Safe Control. Click OK when you're done.

    Create the custom Gallery Source

    The custom Gallery Source is very simple, in this case we only want it to return a single custom Gallery Item. So the implementation should look as follows:

    [Guid("f62379dd-8ec0-402e-8034-7a0bcaaf7a8a")]
    public class ScriptedAdderWebPartGallerySource : WebPartGallerySourceBase {
        public ScriptedAdderWebPartGallerySource(Page page)
            : base(page) {
        }
    
        protected override WebPartGalleryItemBase[] GetItemsCore() {
            return new WebPartGalleryItemBase[] {
                new ScriptedAdderWebPartGalleryItem(this, base.Page)
            };
        }
    }

    Create the custom Gallery Item

    It's in the custom Gallery the magic happens, it's where we tell the WebPartAdder to invoke a JavaScript before adding the Web Part to the page. The implementation is very similar to the one in yesterdays post, and I'll only show you the differences. First of all we need to override the OnClientAdd property, it is a string and should contain the name of the JavaScript method that should be invoked.

    public override string OnClientAdd {
        get {
            return "adderWithScriptDlg";
        }
    }

    Next we need to modify the Instantiate() method. We'll create our custom Web Part using the constructor that takes the data as argument and pass in the value of the WebPartContent property. The WebPartContent property is a property of the Gallery Item that is set during the post back after your JavaScript has been invoked.

    public override System.Web.UI.WebControls.WebParts.WebPart Instantiate() {
        return new ScriptedAdderWebPart(this.WebPartContent);
    }

    This property could basically contain anything, as long as it can be represented as a string. You can create JSON structures for instance if you need to pass more advanced data structures to your Web Part if you perhaps like to set several properties.

    Create the custom JavaScript

    Now it's time to implement the JavaScript that is invoked when the end-user clicks the Add button to add a Web Part. Add the "Layouts" mapped folder to your project and add a new JavaScript file. In this file create a new function with the name you entered in the OnClientAdd property. It is important that it takes three arguments; item, zoneNum and zoneIndex. In this case we would like to open a Modal Dialog and retrieve the Web Part property value, so we implement it as follows:

    function adderWithScriptDlg(item, zoneNum, zoneIndex) {
        var options = {
            url: SP.Utilities.Utility.getLayoutsPageUrl('Wictor.AdderWithScript/AddPage.aspx'),
            title: "Enter the data for the Web Part",
            width: 400,
            height: 300,
            dialogReturnValueCallback: 
                Function.createDelegate(null, function (dialogResult, returnValue) {
                if (dialogResult == 1) {
                    var wpVal = WPAdder._getHiddenField('wpVal');
                    if (wpVal) {
                        wpVal.value = returnValue;
                    }
                    WPAdder.addItemToPage(item, zoneNum, zoneIndex);
                }
            })
        }
        SP.UI.ModalDialog.showModalDialog(options);
    }

    First of all we create the options variable that contains all the options for the Modal Dialog and then show the dialog using the showModalDialog() method. The properties for the modal dialog is configured so that It's pointing to a custom Application Page (we'll create that one in a moment). Then we set some other properties and finally the callback function of the dialog. In the callback we do something interesting - we retrieve a hidden field called wpVal and set the value of that field to the value returned from the modal dialog. It is this property that then is posted back to the WebPartAdder and inserted into the WebPartContent property. And then to actually add the Web Part we need to call back into the WebPartAdder JavaScript API (WPAdder) using the addItemToPage() method.

    Create the custom Application Page

    Now it's time to create the custom Application Page. This is a standard procedure, so I'm not showing you all the details. But basically you add a new Application Page to the mapped Layouts folder and then create a UI. In this case a textbox and a button is sufficient. The server side code of the Application Page should handle the click of the button and return (using JavaScript) the value in the textbox to the callback method. This could be implemented as follows:

    protected void btn_Click(object sender, EventArgs e) {
        Response.Clear();
        Response.Write(
            String.Format(
            "<script type='text/javascript'>window.frameElement.commonModalDialogClose(1,'{0}');</script>",
            data.Text
            ));
        Response.End();
    }

    It's just closing the Dialog with an OK value (1) and then passing the value of the textbox as second argument.

    And finally some CAML!

    What would SharePoint development be without some CAML. We need to add our custom Gallery Source as a Web Part Adder extension and we need to make sure the JavaScript is loaded (for the sake of simplicity I add it to all pages). Modify the elements manifest of your SPI as below:

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <WebPartAdderExtension
            Assembly="$SharePoint.Project.AssemblyFullName$"
            Class="$SharePoint.Type.f62379dd-8ec0-402e-8034-7a0bcaaf7a8a.FullName$"/>
        
        <CustomAction
            Location="ScriptLink"
            ScriptSrc="~site/_layouts/Wictor.AdderWithScript/AdderWithScript.js" />
    
    Elements>
    First I use the WebPartAdderExtension to register the custom Gallery Source and then a CustomAction with Location set to ScriptLink to load the JavaScript.

    Try it out!

    Time to take this baby out for a spin. Deploy the solution and edit a page. When you choose to add a Web Part you should see something that looks like this, depending on what categories etc you set for your custom Gallery Item:

    The Web Part Gallery

    Now when you click Add you should, instead of seeing the Web Part on the page, see a Modal Dialog popping up.

    The custom Modal Dialog

    If you close the dialog without clicking the button your Web Part is not added, but if you write something in the text box and click the button the Web Part should be added to the page with the custom property set as specified in the dialog.

    The awesome result!

    Summary

    Once again the WebPartAdder has proven to be very useful for end-user scenarios where you want to make it easier for users to add and configure Web Parts. Not only can we dynamically populate the Web Part Gallery, we can also force users to specify configuration/information for the Web Parts. Happy devving!

  • Dynamically populate the Web Part Gallery using the WebPartAdder in SharePoint 2010

    Tags: Web Parts, SharePoint 2010

    Writing this post has been on my agenda for some time, initially I intended to put it into my SharePoint 2010 Web Parts in Action book, but there was not enough time, you know how it is! This is an excellent new feature to SharePoint 2010 which allows you to dynamically populate the Web Part Gallery with Categories and Web Parts. So here we go.

    Introduction to the Web Part Adder and the Web Part Gallery

    Think of the List and Libraries category in the Web Part Gallery - it is dynamically populated with the lists and libraries available in the current web. This is all done using the WebPartAdder class which loads all the Web Parts available in the gallery from a number of different sources, see figure below. These source include the List and Libraries category, the local Web Part catalog, files in the wpcatalog, closed and uploaded Web Parts etc.

    WebPartAdder and sources

    The really cool thing with this is that you can actually create custom Gallery Sources! This is a new feature of SharePoint 2010 and is really simple to do. I'll show you how!

    Create a custom Web Part Gallery Source

    I've not yet seen any guide on how to create a custom Web Part Gallery Source, even though the classes and methods in MSDN are documented (the MSFT minimalistic way). To get this all working you need to use a new Feature element available in the Element manifest called WebPartAdderExtension. This element is referenced only once in MSDN, where it only says that the element is not documented!

    In this walkthrough I will use a very simple custom gallery source. It will dynamically populate the gallery with Product Web Parts that displays information about products. The product information is stored within a SharePoint list, in the local site, called Products.

    The product list

    From this list we'll create a new category in the gallery that lists all products, and when a product is added to the page it should add a new Web Part displaying that particular product information.

    Create a new SharePoint project

    imageStart by creating a new Empty SharePoint project. Make it a farm solution. Then add a new Web Part SPI - this will also add a Site Collection scoped feature to your project. In the Web Part SPI remove the .webpart file. We do not want to add this Web Part to the gallery - we only need the Web Part class. You can of course make the Web Part without an SPI if you want to.

    Next step is to build the Web Part user interface - and here you can get fancy if you like. If you feel for a copy and paste excursion you can copy and paste the code below.

    public class ProductWebPart : WebPart {
        public ProductWebPart() {
        }
        public ProductWebPart(SPListItem item) {
            ProductId = item.ID;
        }
        protected override void CreateChildControls() {
            SPList productList = SPContext.Current.Web.Lists.TryGetList("Products");
            if (productList != null) {
                try {                    
                    SPListItem item = productList.GetItemById(ProductId);
                    this.Title = "Product information:" + item.Title;
                    this.Controls.Add(new LiteralControl(
                        String.Format("Product: {0} costs ${1}", item.Title, item["Price"])));
                }
                catch (ArgumentException) {
                    this.Title = "Unknown product";
                    this.Controls.Add(new LiteralControl("Product not found"));
                }
            }
        }
    
        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable]
        public int ProductId { get; set; }
    }

    As you can see it's a simple Web Part with one property ProductId that contains the id of the product to be listed. A specific constructor has been added which takes an SPListItem as argument - this one is used later by the custom source to instantiate the Web Part.

    The CreateChildControls is very simple and just writes the name of the product and its price, if the product is found - otherwise it shows an error.

    Create the Custom Web Part Gallery Source

    Next is to create the Custom Web Part Gallery Source. First add a new Empty Element SPI to your project - the SPI will automatically be associated with the feature that was created by the Web Part SPI (unless you installed Waldeks fancy Visual Studio extensions :-).

    In that SPI add two new classes; ProductsWebPartGallerySource and ProductsWebPartGalleryItem. The first one is the actual custom source and the second class represents the items in that source.

    The ProdcutsWebPartGallerySource is responsible for discovering and iterating the items for custom gallery extension. This class must derive from the WebPartGallerySource and implement one constructor as well as one method as follows:

    [Guid("01db1e81-5853-448e-b8c7-4b6564994ae3")]
    public class ProductsWebPartGallerySource : WebPartGallerySourceBase {
        public ProductsWebPartGallerySource(Page page)
            : base(page) {
        }
    
        protected override WebPartGalleryItemBase[] GetItemsCore() {
            List<WebPartGalleryItemBase> items = 
                new List<WebPartGalleryItemBase>();
            SPList list = SPContext.Current.Web.Lists["Products"];
            foreach (SPListItem item in list.Items) {
                items.Add(
                    new ProductsWebPartGalleryItem(this, base.Page, item));
            }
                
            return items.ToArray();
        }
       
    }

    The required constructor required only passes on to its base class. The overridden GetItemsCore() method is the method that is responsible for returning all Web Parts discovered by this source. So in this case the method simply iterates over all available items in the Products list and creates a ProductsWebPartGalleryItem object. Also notice that I added the Guid attribute to the class - we'll need that later.

    Now it's time to implement the gallery items. This is done in the second class file you created. The ProductsWebPartGalleryItem should be derived from the abstract class WebPartGalleryItemBase. It is implemented as follows:

    public class ProductsWebPartGalleryItem : WebPartGalleryItemBase {
    
        private readonly string title;
        private readonly SPListItem item;
    
        public ProductsWebPartGalleryItem(WebPartGallerySource source, Page page, SPListItem item)
            : base(source, page) {
            this.item = item;
            this.title = item.Title;
        }
    
        public override System.Web.UI.WebControls.WebParts.WebPart Instantiate() {
            return new ProductWebPart.ProductWebPart(item);
        }
    
        public override string Category {
            get { return "Products"; }
        }
    
        public override string Description {
            get { return "Show listing for product: " + title; }
        }
    
        public override string IconUrl {
            get { return "/_layouts/Wictor.Adder/product.png"; }
        }
    
        public override string Id {
            get { return item.ID.ToString(); }
        }
    
        public override bool IsRecommended {
            get { return false; }
        }
    
        public override string Title {
            get { return title; }
        }
    }

    This implementation has one constructor, taking the source, the current page and the specific list item as arguments. It stores some values locally in the class and passes the source and page to its base class. Before discussing the Instantiate() method let's take a look at the properties. These are the minimum properties required for the implementation to work, but there are several more that can be used to do some nifty stuff! Such as the ClientAdd method which allows you to specify a JavaScript method to execute when the Web Part is added or the RibbonCommand which allows you to execute a specific Ribbon command. What they do is pretty self explanatory! Interesting thing here is that you do not need to have the same category on all Web Parts in the source - you can populate several categories in the gallery, new or existing.

    The Instantiate() method is responsible for creating the Web Part with the correct properties and is called by the WebPartAdder and the custom source when a Web Part is added to the page. In this case we create the Web Part using the custom constructor and pass in the list item.

    So now all the code are done and it should compile fine. There is just one small thing left - the mysterious WebPartAdderExtension element. In your empty element SPI open the elements manifest file and make it look like the following:

    Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <WebPartAdderExtension 
            Assembly="$SharePoint.Project.AssemblyFullName$" 
            Class="$SharePoint.Type.01db1e81-5853-448e-b8c7-4b6564994ae3.FullName$"/>
    </Elements>

    As attribute values I use the Visual Studio replaceable tokens for the assembly full name and for the full name of the custom Web Part Gallery source class - here's the usefulness of the Guid attribute, no need to remember the class name and namespace and it allows for easier refactoring.

    As a final icing on the cake I also added a sweet little image to be used in the gallery. Your solution should look like this:

    image

    Ok, we're done!

    Test the custom Web Part Gallery Source!

    Now it is time to take this for a test drive. Deploy your solution, go to a page and edit it. Then click on Insert > Web Part. It should look something like this:

    SNAGHTML11b9c05

    The items in the Product list ends up as Web Parts in the Products category, with the sweet little icon. You can now choose a Web Part and insert into the page and see how it renders the correct information!

    Summary

    You've now seen how you can extend the Web Part Gallery with custom Web Part Gallery Sources. It is fairly simple and it can be very useful if you want to help the users by creating pre-configured Web Parts. I can see really many good use cases of this. Oh, I forgot - this does not work in the Sandbox.

  • Understanding the SharePoint 2010 Sandbox limitations

    Tags: Web Parts, SharePoint 2010

    Recent discussions I've been involved with and blog posts have highlighted some of the SharePoint 2010 Sandbox limitations (either as bugs or as a feature). I have also talked about this during SEF 2010 and SPCSEA 2010. While writing my book SharePoint 2010 Web Parts in Action I had the opportunity to discover these limitations early on and  have learned to live with it. If you read my book you will find a lot of references to "this does not work in the Sandbox" (you've already ordered it huh? Otherwise it's just one click away).

    In this post I want to give you all a little head start on what really happens when executing SharePoint 2010 Sandboxed solutions. Focus is here on Web Parts.

    SharePoint 2010 Sandbox Execution flow

    Before building solutions for the Sandbox you have to know how it actually works, that will also make you understand in more details why some things work and some don't.

    1. The "real" Page object exists in the W3WP.exe process
    2. The Sandboxed Execution Manager serializes information from the fully-trusted objects (see below)
    3. The serialized is sent to the User Code Service (in the OnPageLoadComplete event). It can be on the same or a specific Sandboxed App Server
    4. The User Code Service reuses or spins up a Sandbox Worker process and sends request to the worker process
    5. The User Code Worker Process recreates a HttpContext and the Page object.
    6. It then creates a Form, Web Part Manager and a Zone before it processes the page.
    7. After processing the Sandboxed Page object it retrieves the Response, View State, Control State (execution depends on for instance it is a post-back, export of web part, edit web part etc)
    8. Data is once serialized and sent back to the execution manager
    9. The information is put back into the "real" objects (Web Part properties, view state, controls state...)

    Sandbox details

    Serialized information

    The information that is serialized includes but are not limited to:

    • ID's of Form, Web Part Manager, Zone, Toolpane
    • Web Part properties
    • Options and properties of the Web Part and zone, such as chrome, zone customization, width, height...
    • View state
    • Control state
    • Server Variables (except APPL_PHYSICAL_PATH and PATH_TRANSLATED)
    • Request Headers
    • Input Stream
    • Current context (List Id, Item Id)
    • Query String

    Non accessible or working stuff

    You cannot access the following things from a Sandboxed Web Part, even though it compiles fine and executes without any errors:

    • The Cache object (works but is not serialized back)
    • The ScriptManager (works but is not serialized back)
    • The ClientScriptManager (works but is not serialized back)
    • The HttpRequest.Files collection (will never contain anything) [Corrected] 
    • The Master Page (works but is not serialized back)
    • Other Web Parts (since it creates a new Page and Form object and only adds your SB:d Web Part to the page)
    • Embedded resources (these are requested by the WebResource.axd and they cannot resolve the Sandboxed assemblies from the W3WP.exe process) [Added after initial post] 
    • You cannot use redirection (Response.Redirect, Server.Transfer or SPUtility.Redirect) [Added after initial post - Thanks Todd Bleeker] 
    • You cannot export a Sandboxed Web Part (it will just export the SPUserCodeWebPart) [Added after initial post] 

    I hope this little post helps you out understanding why some of the stuff you expect to work doesn't.

    Feel free to comment on this and correct me if I wrote anything wrong...

  • Nifty trick with Visual Studio 2010 replaceable parameters for SharePoint 2010 Web Parts

    Tags: Visual Studio, Web Parts, SharePoint 2010

    MP900408848[1]If you have been working with SharePoint 2010 development using Visual Studio 2010 you have most certainly stumbled upon the new replaceable parameters that replaces data in your solution files during the packaging process. For instance Visual Studio uses $SharePoint.Project.AssemblyFullName$ in the Web Part control description (.webpart) files and this is replaced with the assembly full name (strong name) during packaging. By default it looks like this when you create a new Web Part:

    type name="Project.MyWebPart, $SharePoint.Project.AssemblyFullName$" />

    After the packaging and when deployed into SharePoint it looks like this:

    type name="Project.MyWebPart, Project, Version=1.0.0.0, Culture=neutral, PublicKeyToken=54c0c201dd8d1c31" />

    This saves you some time when changing versions etc of the assembly.

    But what about if you change the name of the class or the namespace, then you have to rename a whole lot of things; the CS file, the .webpart file, optionally the element manifest and of course all references. A better way is to use another replaceable parameter that replaces the token with the full name of the type. First of all you need to specify a Guid attribute on the type (Web Part class in this case) like this:

    [ToolboxItemAttribute(false)]
    [Guid("A4D3BE9B-E2D6-42A4-B4F9-D78911C214E8")]
    public class MyWebPart : WebPart{...}

    Then you update the .webpart file to use the replaceable parameter that has the format of:

    $SharePoint.Type.GUID.FullName$

    The GUID must be lower-case and your updated .webpart file should look like this after copying the Guid value from the attribute:

    type name="$SharePoint.Type.a4d3be9b-e2d6-42a4-b4f9-d78911c214e8.FullName$, $SharePoint.Project.AssemblyFullName$" />

    Visual Studio 2010 will now replace this during runtime with whatever you Web Part class name and namespace is, so you can feel safe renaming and refactoring.

    Even better is that this works for all other cases where you need to reference a type in an element manifest, user control or similar. Out-of-the-box the following file types will be parsed and parameters replaced; XML, webpart, DWP, ASCX and ASPX. For instance you might have added a event receiver for a content type - just add the same two tokens used in the sample above in the Assembly and Class elements of the Receiver element.

  • Enhancing the SharePoint 2010 Tag Profile Page with Bing news

    Tags: Web Parts, SharePoint 2010

    The Tag Profile Page in SharePoint 2010 is used by the Managed Metadata Service (MMS) as a landing page for a term or a keyword. It is used to describe the tag, its location in the taxonomy, synonyms etc. It also contains all the latest tagged items and a note board.

    Tag Profile Page

    The page is quite dull out of the box. Fortunately this page is a Web Part Page and can be customized as you like! Get Connected Web PartYou can add Web Parts and rearrange the page. There is not much you can do with the Tag Profile Web Part, but you can edit the Tagged Items Web Part and change how many days it should go back to look for tagged items (default 60 days). The Get Connected Web Part can be slightly configured with what links it will show, see image to the right. And the Noteboard Web Part also has some configuration options such as how many notes to show etc.

    You could add some more out of the box Web Parts if you like but none of them integrates with the current term, not even through Web Part connections.

    Wouldn't it be awesome to connect the tag to an outside service like...let's say Bing News, and see if there are any related news to the tag? Just like below? The image shows the standard RSS Web Part in SharePoint 2010 which is configured to query Bing News for the current term.

    Tag Profile connected to Bing News

    To achieve this I whipped together a small Provider Web Part that takes the term-id from the query string, looks up the value in the term store and then make that tag name available through an IWebPartField connection. This provider Web Part has one property which is used to set the name of the field. That field is then used by the RSS Web Part to create the query string to get the RSS feed. The provider Web Part is configured to be hidden on the page so that it is not seen by the users.

    The code for the Web Part looks like this:

       1:  namespace Wictor.SocialExtensions.SocialTagInfoWebPart {
       2:      [ToolboxItemAttribute(false)]
       3:      public class SocialTagInfoWebPart : WebPart, IWebPartField {
       4:          string socialTagName;
       5:          Guid termId;
       6:          
       7:   
       8:          protected override void OnLoad(EventArgs e) {
       9:              try {
      10:                  termId = new Guid(this.Page.Request["termid"]);
      11:                   
      12:              }
      13:              catch (FormatException) {
      14:                  termId = Guid.Empty;
      15:              }
      16:              // get the tag name
      17:              TaxonomySession taxonomySession = new TaxonomySession(SPContext.Current.Site); 
      18:   
      19:              Term term = taxonomySession.GetTerm(termId);   
      20:              socialTagName = term.Name;
      21:   
      22:              base.OnLoad(e);
      23:          }
      24:          protected override void RenderContents(HtmlTextWriter writer) {
      25:              writer.Write(string.Format("id:{0}, tag:{1}",termId,socialTagName));
      26:              base.RenderContents(writer);
      27:          }
      28:   
      29:          [WebBrowsable(true)]
      30:          [Personalizable(PersonalizationScope.Shared)]
      31:          [WebDisplayName("Filter name")]
      32:          public string FilterName {
      33:              get;
      34:              set;
      35:          }
      36:          public void GetFieldValue(FieldCallback callback) {
      37:              callback.Invoke(this.socialTagName);
      38:          }
      39:   
      40:          public string TagName {
      41:              get {
      42:                  return socialTagName;
      43:              }
      44:          }
      45:   
      46:          public PropertyDescriptor Schema {
      47:              get {
      48:                  return TypeDescriptor.CreateProperty(this.GetType(), this.FilterName, typeof(string));
      49:              }
      50:          }
      51:          [ConnectionProvider("Social Tag name")]
      52:          public IWebPartField GetConnectionFieldProvider() {
      53:              return this;
      54:          }
      55:      }
      56:  }

    This is a standard Web Part that exposes the IWebPartField interface (line 3) (which the RSS Web Part consumes). In the OnLoad (line 8) method the termid parameter is retrieved from the query string and this is used to lookup the name of the term using the TaxonomySession object (line 17) and stored in the local property socialTagName. The RenderContents (line 24) is used when in editing mode to display the status of the Web Part. The configurable property FilterName (line 32) is exposed so that the editor can change the name of the filter value that is sent to the consumer. For instance the Bing News RSS feed URL expects that the query parameter has the value "Query". The IWebPartField interface requires that the GetFieldValue and Schema methods are implemented. The GetFieldValue invokes the callback with the local property socialTagName and the Schema property returns a PropertyDescriptor of the type string and with the name equal to the FilterName property. Finally the provider connection end-point is configured.

    Configure Connect The TagWhen the Web Part is deployed and feature activated on the My Site Site Collection you can edit the Tag Profile page and add the SocialTagInfoWebPart to the page. Configure it so that it is hidden and set the Filter name property to Query.

    Then add the RSS Web Part to the page. Configure the Web Part, give it a meaningful name like Related on Bing and set the RSS Feed URL to "http://api.bing.com/rss.aspx?Source=News&Market=en-US&Version=2.0". This is the URL that will be used to query Bing News.

    To connect the provider Web Part with the RSS Web Part edit the hidden provider Web Part and select Connections > Send Social Tag name To > Related on Bing. In the dialog box select Get Feed Parameter From and click Finish. Then save your page. When the connection is established the RSS Web Part will append the filter name and social tag name to the RSS Feed URL, for instance http://api.bing.com/rss.aspx?Source=News&Market=en-US&Version=2.0&Query=SharePoint

    Connections

    That is all needed to enlighten the Tag Profile Page. A little bit of coding can always sharpen up your SharePoint.

    If you would like to connect it to other RSS sources, just edit the URL in the RSS Web Part and the Filter name in the provider Web Part.

    Note: there are for sure other ways to do this and I bet the SharePoint "no-code" specialists will seconds after this post is available show you how to do it with a little bit of jQuery magic :)

    Until next time...

  • Status of ChartPart for SharePoint 2010

    Tags: SharePoint, Web Parts, CodePlex, SharePoint 2010

    Chart Part

    I have recently been getting quite a few requests and comments about the status of ChartPart for SharePoint - a charting Web Part that I built about a year ago and shared on Codeplex. This latest version have had more than 6.000 downloads which I think is amazing, version 1 had close to 10.000 downloads.

    I temporarily put this project on hold a couple of months a go, due to two major reasons; the built-in Chart Web Part in SharePoint 2010 and that I'm currently writing a book (which essentially means that I have no time at all). Now we now that the out-of-the-box charting Web Part is SharePoint 2010 Server Enterprise only and I only have one and half chapters left on the book.

    So I aim to produce a new and improved ChartPart for SharePoint 2010 as soon as I return from my (well deserved IMHO) vacation.

    If you have any requests, ideas or rants about ChartPart for SharePoint then head on over to the Codeplex site and discuss or submit a feature request.

  • Custom application pages in the SharePoint 2010 Sandbox

    Tags: Web Parts, SharePoint 2010

    The Sandbox in SharePoint 2010 allows Site Collection administrators to upload solutions in their Site Collections without access to the physical server. This is a great way to open up for creativity and for each Site Collection owner to expand the functionality of their Site Collection without adventuring the stability of the SharePoint farm. Sandbox Solutions do have some limitations, for instance we cannot add new Application Pages. Application pages are normally pages added to the _layouts folder, which are located in the {SharePoint Root}\TEMPLATE\LAYOUTS physical folder on each server.

    Application pages or similar are often used in different scenarios such as when you are building configuration or settings pages. I use them quite often and felt a bit limited with building Sandboxed solutions without them.

    Sandboxed solutions still allows us to upload Content Pages, that is pages that are located in a document library for instance. So one workaround is to build a Web Part containing the custom logic and a Content Page that contains this Web Part. Then deploy this to the Solution gallery in your Site Collection. And this is how to do it:

    Create a project

    Create a new Empty SharePoint 2010 project using Visual Studio 2010 and deploy it as a Sandboxed solution.

    Add a Web Part item

    Solution ExplorerThen add a new Web Part item to your project. Remove the Web Parts Control Description file (.webpart) and the Elements.xml file. We do not want to add the Web Part to the Web Part gallery, this Web Part will only be used by our Sandboxed Application Page.

    Then build your control logic in the Sandboxed Web Part.

    Add a Module item

    In the Web Part item add a new Module item. Rename the Sample.txt file to AdminPage.aspx or similar - just make sure the extension is .aspx. Your Solution Explorer should then look like the image to the right.

    Edit the URL and location in the elements.xml file if you want to deploy it in a document library or any other location. If you have named your items as shown above your page will end up at http://site/AdminPage/AdminPage.aspx.

    Edit the ASPX page

    Open up the the AdminPage.aspx and build a standard Web Part Page. You can copy the source from a basic Web Part Page using SharePoint Designer for instance. The source should look something like this when you cleaned it up:

    <%@ Page language="C#" 
      MasterPageFile="~masterurl/default.master"  
      Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c"%>
    <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" 
      Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    
    <asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
    Sandboxed Admin Page
    asp:Content>
    
    <asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
    Sandboxed Admin Page
    asp:Content>
    
    <asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">
    <style type="text/css">
    body #s4-leftpanel {
        display:none;
    }
    .s4-ca {
        margin-left:0px;
    }
    style>
    asp:Content>
    
    <asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server">asp:Content>
    
    <asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
    
    asp:Content>

    In this Web Part Page I have removed all unnecessary page directives and only kept the Page directive with the master page reference and the import of the Microsoft.Sharepoint.WebPartPages namespace, which we will soon use. In the PlaceHolderAdditionalPageHead some CSS is added to remove the Quick Launch and I added a page title and heading.

    Of course you can use any kind of HTML in here. You cannot use code-behind or inline server-side code though.

    Add the Web Part

    In the PlaceHolderMain the Web Part will be added. This is done by using the SPUserCodeWebPart, which is a wrapper for Web Parts that lives in the Sandbox. In my case it will look like this:

    <WebPartPages:SPUserCodeWebPart 
        runat="server" 
        Description="Admin" 
        Title="Admin" 
        AssemblyFullName="$SharePoint.Project.AssemblyFullName$" 
        SolutionId="473f9e55-bf55-4283-a9ce-3de0b05650f7" 
        ID="adminwp"     TypeFullName="Wictor.SBAppPage.AdminWebPart.AdminWebPart" >
    WebPartPages:SPUserCodeWebPart>

    Here we need to edit two things. First the TypeFullName must be the full name of your Web Part, just check the .cs file of your Web Part if you don't know how to get it. Secondly we need to set the SolutionId attribute to the solution id value of our solution. You can get a hold of this id by opening up the Package Editor and select Manifest. Then check the Solution element for the SolutionId attribute and just copy it.

    SolutionId

    The AssemblyFullName attribute contains a Visual Studio replaceable parameter which inserts the full name of your assembly.

    Deploy and enjoy!

    That's it - just deploy your solution and navigate to your custom sandboxed application page.

    Ready for action!

AWS Tracker

About Wictor...

Wictor Wilén is a Director and SharePoint Architect working at Connecta AB. Wictor has achieved the Microsoft Certified Architect (MCA) - SharePoint 2010, Microsoft Certified Solutions Master (MCSM) - SharePoint  and Microsoft Certified Master (MCM) - SharePoint 2010 certifications. He has also been awarded Microsoft Most Valuable Professional (MVP) for four consecutive years.

And a word from our sponsors...

SharePoint 2010 Web Parts in Action